繁体   English   中英

Rust 相当于 Java 策略模式的消费者接口

[英]Rust equivalent of Java Consumer interface for Strategy pattern

我将提供一个实际的例子。

我想创建一个事件记录器。 我将事件定义为接口:

import java.util.function.Consumer;

interface Event {}

class BuyEvent implements Event {}

class SellEvent implements Event {}

记录器只是事件的消费者:

public static void main(String[] args) {
        Consumer<Event> logger;

        // Logger with method reference
        logger = System.out::println;
        logger.accept(new BuyEvent());

        // Logger with lambda
        logger = (event) -> {
            // Do something else
            System.out.println(event);
        };
        logger.accept(new BuyEvent());

我还可以使用 state 创建一个记录器。例如:

class StatefulLogger implements Consumer<Event> {
    public StatefulLogger() {
    }

    @Override
    public void accept(Event event) {
        // Change state, then print event
        System.out.println(event);
    }
}

我可以按如下方式使用有状态记录器:

public static void main(String[] args) {
        Consumer<Event> logger = new StatefulLogger("foo.txt");
        logger.accept(new BuyEvent());
}

我正在尝试在 Rust 中实现相同的目标。

我将事件定义为枚举:

#[derive(Debug)]
enum Event {
    BuyEvent,
    SellEvent,
}

我定义了一个 Logger 特征和一个带有 state 的结构来实现这样的特征:

trait Logger {
    fn accept(&mut self, ev: Event);
}

struct StatefulLogger {}

impl Logger for StatefulLogger {
    fn accept(&mut self, ev: Event) {
        // Change state, then print event
        println!("{:?}", ev);
    }
}

我可以按如下方式使用记录器:

fn main() {
    let logger: &dyn Logger = &ComplexLogger {};
}

我希望能够为记录器分配一个闭包,与 Java 的精神大致相同。

fn main() {
    let consumer: fn(Event) = |ev: Event| {
        println!("{:?}", ev);
    };
}

回顾一下:

在 Java 中,我使用 Consumer 接口使用 Strategy 设计模式实现了一个记录器。 记录器既可以是复杂的有状态的 object,也可以是轻量级的 lambda。

我想在 Rust 中实现相同的目标,但我不知道如何进行。 我无法在 Inte.net 上找到类似的示例。 此外,Rust 是否提供类似于 Java 的 Consumer 接口?

没有办法在 Rust 中快速解决这个问题,但您可以创建自己的宏将 lambda 转换为 Logger impl,然后返回其 object。看看这个repo 如果你愿意,我可以很快写一个解决方案。 以其他方式,您可以将Logger trait更改为结构,其中为消费者定义字段。 它使您可以将任何Fn(Event)作为消费者使用,即如果您有 state 的记录器,您可以将其移动到 lambda 并传递它或直接传递一些 fn。

#[derive(Debug)]
struct Event;

struct Logger<T>
where
    T: Fn(Event),
{
    consumer: T,
}

impl<T> Logger<T>
where
    T: Fn(Event),
{
    fn new(consumer: T) -> Self {
        Self { consumer }
    }

    fn accept(&self, event: Event) {
        (self.consumer)(event);
    }
}

struct StatefulLogger;

impl StatefulLogger {
    fn log(&self, event: Event) {
        println!("{:?}", event);
    }
}

fn log_fn(e: Event) {
    println!("{:?}", e);
}

fn main() {
    let foo = |e: Event| println!("{:?}", e);
    let logger_lambda = Logger::new(foo);

    let stateful_logger = StatefulLogger;
    let logger_struct = Logger::new(move |e| stateful_logger.log(e));

    let logger_fn = Logger::new(log_fn);

    logger_lambda.accept(Event);
    logger_struct.accept(Event);
    logger_fn.accept(Event);
}

关于用户界面,请查看 Fn、FnMut 和 FnOnce 特性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM