vendredi 27 janvier 2023

Rust equivalent of Java Consumer interface for Strategy pattern

I will provide a practical example.

I want to create an event logger. I define an event as an Interface:

import java.util.function.Consumer;

interface Event {}

class BuyEvent implements Event {}

class SellEvent implements Event {}

A logger is simply a Consumer of events:

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());

I can also create a logger with state. For example:

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

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

I can use the stateful logger as follows:

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

I am trying to achieve the same in Rust.

I define an event as an enum:

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

I define a Logger trait and a struct with state that implements such trait:

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);
    }
}

I can use the logger as follows:

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

I would like to be able to assign a closure to the logger, much in the same spirit of Java.

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

To recap:

In Java, I had implemented a logger using a Strategy design pattern using the Consumer interface. A logger could both be a complex stateful object but also a lightweight lambda.

I would like to achieve the same in Rust, but I don't know how to proceed. I was not able to find similar examples on the Internet. Also, does Rust provide an analogous to Java's Consumer interface?

Aucun commentaire:

Enregistrer un commentaire