我将提供一个实际的例子。
我想创建一个事件记录器。我将一个事件定义为一个接口:
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());
我还可以创建一个带有状态的日志记录器。例如:
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());
}
我也在努力实现同样的目标。
我将事件定义为枚举:
#[derive(Debug)]
enum Event {
BuyEvent,
SellEvent,
}
我定义了一个Logger trait和一个带有状态的struct来实现这样的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);
}
}
我可以按如下方式使用记录器:
fn main() {
let logger: &dyn Logger = &ComplexLogger {};
}
我希望能够为日志记录器分配一个闭包,这与Java的精神非常相似。
fn main() {
let consumer: fn(Event) = |ev: Event| {
println!("{:?}", ev);
};
}
总结一下:
在Java中,我使用策略设计模式和消费者接口实现了一个日志记录器,日志记录器既可以是一个复杂的有状态对象,也可以是一个轻量级的lambda。
我也想在Rust中实现同样的功能,但是我不知道该怎么做。我在互联网上找不到类似的例子。另外,Rust是否提供了一个类似于Java的消费者接口?
1条答案
按热度按时间ntjbwcob1#
在Rust中没有办法快速解决这个问题,但是你可以创建自己的宏来将lambda转换为Logger impl,然后返回它的对象。看看这个repo。如果你愿意,我可以很快写一个解决方案。另外,你可以将你的
Logger trait
改为struct,定义消费者的字段。它让你可以使用任何Fn(Event)
作为消费者,也就是说,如果你有带状态的记录器,你可以把它移到lambda并传递它,或者直接传递一些fn。关于消费者界面,看看Fn,FnMut和FnOnce特性。