
本文介绍如何在 rust 中模拟 java 的 `consumer
在 Rust 中,虽然没有直接对应 Java Consumer
下面是一个生产就绪的 Logger 实现,兼顾简洁性、类型安全与策略统一性:
#[derive(Debug, Clone, Copy)]
enum Event {
BuyEvent,
SellEvent,
}
// 泛型 Logger:封装任意可调用对象,要求其能消费 Event
struct Logger
where
F: Fn(Event),
{
consumer: F,
}
impl Logger
where
F: Fn(Event),
{
fn new(consumer: F) -> Self {
Self { consumer }
}
fn accept(&self, event: Event) {
(self.consumer)(event);
}
}
// 示例:有状态日志器(如写入文件、计数等)
struct StatefulLogger {
count: usize,
}
impl StatefulLogger {
fn new() -> Self {
Self { count: 0 }
}
fn log(&mut self, event: Event) {
self.count += 1;
println!("[{}] {:?}", self.count, event);
}
}
fn main() {
// ✅ 1. 无状态闭包(类似 Java lambda)
let logger_lambda = Logger::new(|e| println!("Lambda: {:?}", e));
// ✅ 2. 普通函数(类似 Java 方法引用)
fn simple_log(e: Event) {
println!("Fn: {:?}", e);
}
let logger_fn = Logger::new(simple_log);
// ✅ 3. 有状态结构体 → 通过 move 闭包捕获并调用
let mut stateful = StatefulLogger::new();
let logger_stateful = Logger::new(move |e| stateful.log(e));
// 统一调用入口
logger_lambda.accept(Event::BuyEvent);
logger_fn.accept(Event::SellEvent);
logger_stateful.accept(Event::BuyEvent); // 注意:此处 stateful 已被 move 进闭包,无法复用
} ⚠️ 重要注意事项:
- 若需多次使用有状态对象(如 StatefulLogger),应改用 FnMut + &mut self 方式:将 Logger 改为 struct Logger
where F: FnMut(&mut StatefulLogger, Event),或更推荐——直接让 StatefulLogger 自身实现 FnMut (即 impl FnMut for StatefulLogger),但这需手动实现 call_mut,通常不必要; - Fn 要求闭包只读捕获环境;若需修改捕获变量(如计数器),请改用 FnMut 并调整 accept 为 &mut self;
- 避免过度泛型:若所有日志器都需共享生命周期或动态分发,可结合 Box
或 Arc >,但会牺牲零成本抽象优势。
✅ 总结:Rust 的策略模式不依赖接口继承,而依托于 trait object 或泛型闭包。Logger
立即学习“Java免费学习笔记(深入)”;










