如何在Rust中实现类似Java Consumer接口的策略模式日志器?
在Rust中实现类似Java Consumer接口的事件日志器策略模式
Java中的实现参考
Java通过Consumer接口结合策略模式,实现了兼具轻量闭包/方法引用和有状态对象的事件日志器:
事件定义与基础接口
import java.util.function.Consumer; interface Event {} class BuyEvent implements Event {} class SellEvent implements Event {}
轻量实现(方法引用、Lambda)
public static void main(String[] args) { Consumer<Event> logger; // 方法引用实现 logger = System.out::println; logger.accept(new BuyEvent()); // Lambda表达式实现 logger = (event) -> { // 可添加额外逻辑 System.out.println(event); }; logger.accept(new BuyEvent()); }
有状态复杂实现
class StatefulLogger implements Consumer<Event> { // 可添加状态字段,如文件路径、日志计数等 private String filePath; public StatefulLogger(String filePath) { this.filePath = filePath; // 初始化状态,如打开日志文件 } @Override public void accept(Event event) { // 更新状态后处理事件 System.out.printf("[%s] %s%n", filePath, event); } } // 使用示例 public static void main(String[] args) { Consumer<Event> logger = new StatefulLogger("foo.txt"); logger.accept(new BuyEvent()); }
Rust中的实现方案
Rust没有内置和Java Consumer完全等价的接口,但可以通过两种方式实现相同的策略模式效果:
先定义Event枚举
#[derive(Debug)] enum Event { BuyEvent, SellEvent, }
方案一:直接使用闭包类型(简洁轻量)
利用Rust的闭包特性,FnMut(Event) 类型对应Java Consumer的行为(FnMut支持修改闭包捕获的状态):
fn main() { // 基础Lambda式日志器 let mut logger: Box<dyn FnMut(Event)> = Box::new(|ev| { println!("{:?}", ev); }); logger(Event::BuyEvent); // 带捕获状态的闭包日志器 let mut log_count = 0; let mut stateful_logger: Box<dyn FnMut(Event)> = Box::new(move |ev| { log_count += 1; println!("第{}次日志: {:?}", log_count, ev); }); stateful_logger(Event::BuyEvent); stateful_logger(Event::SellEvent); }
方案二:自定义Trait兼容闭包与自定义对象(贴近Java风格)
自定义Logger Trait,并为闭包类型实现该Trait,同时支持自定义有状态结构体:
// 定义Logger Trait,对应Java Consumer的accept方法 trait Logger { fn accept(&mut self, ev: Event); } // 为所有FnMut(Event)类型实现Logger Trait,兼容闭包和函数 impl<F: FnMut(Event)> Logger for F { fn accept(&mut self, ev: Event) { self(ev); } } // 有状态的自定义日志器结构体 struct StatefulLogger { log_count: u32, log_file: String, } impl StatefulLogger { fn new(log_file: &str) -> Self { StatefulLogger { log_count: 0, log_file: log_file.to_string(), } } } impl Logger for StatefulLogger { fn accept(&mut self, ev: Event) { self.log_count += 1; println!("[{}] 第{}次日志: {:?}", self.log_file, self.log_count, ev); } } fn main() { // 使用闭包作为Logger let mut lambda_logger: Box<dyn Logger> = Box::new(|ev| { println!("Lambda日志: {:?}", ev); }); lambda_logger.accept(Event::BuyEvent); // 使用有状态自定义Logger let mut stateful_logger = StatefulLogger::new("foo.txt"); stateful_logger.accept(Event::BuyEvent); stateful_logger.accept(Event::SellEvent); // 使用现有函数作为Logger(方法引用等价) fn log_with_func(ev: Event) { println!("函数式日志: {:?}", ev); } let mut func_logger: Box<dyn Logger> = Box::new(log_with_func); func_logger.accept(Event::SellEvent); }
方案对比
- 方案一:代码简洁,直接利用Rust闭包特性,适合快速实现轻量日志逻辑;
- 方案二:风格贴近Java的接口模式,便于扩展自定义日志器实现,同时兼容闭包和函数引用。
内容的提问来源于stack exchange,提问作者steddy
相关产品推荐
相关产品推荐

