You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 18:40:55