Java:实现将不同实例重定向到不同订阅者的观察者模式的最佳方法是什么



我有一个具有不同子类(RecordA、RecordB等(的类Record。我有一个类,它接收一些对象并创建不同的记录。我想要一个类似观察者模式的东西,但观察者只在某些子类型中插入。

例如,我有一个观察者,他想接收RecordA和RecordC的所有实例。另一个观察者想要接收RecordB的所有实例。

做这样的事情最好的方法是什么?

有两种基本方法:

  • 在观察者中进行筛选:每个观察者都会收到所有记录的通知。然后,观察者过滤掉感兴趣的记录并丢弃其他通知。当通知是本地的(进程间通信(时,这是一种简单易行的方法
  • 在可观察对象中筛选:每个观察者在注册时定义他想要接收的通知(记录类型(。然后,只有当记录与订阅匹配时,observable才会过滤并通知观察者。这有点复杂,需要预订选项的记账,但需要为非本地(进程内(通信付费

代码示例:

用于一般类型M:的消息的Observer

public interface Observer<M> {
void notify(M message);
}

支持两种变体的Observable:在可观察对象中进行过滤,而不进行过滤(然后可以在观察对象中完成(:

public interface Observable<M> {
void subscribe(Observer<M> observer, Predicate<M> filter);
default void subscribe(Observer<M> observer) {
subscribe(observer, message -> true);
}
}

一个简单的通用默认实现:

public class SimpleObservable<M> implements Observable<M> {
private Map<Observer<M>, Predicate<M>> subscriptions = new HashMap<>();
@Override
public void subscribe(Observer<M> observer, Predicate<M> filter) {
subscriptions.put(observer, filter);
}
public void notifyObservers(M message) {
subscriptions.forEach((observer, filter) -> {
if (filter.test(message)) observer.notify(message);
});
}
}

一切都在起作用:一个可观察的日期/时间消息(Temporal的实现(,以及四个对不同日期/时间类感兴趣的不同观察者,其中两个过滤订阅,一个自己过滤,一个只消耗所有事件:

Observer<Temporal> timeObserver = message -> System.out.println("The time is: " + message);
Observer<Temporal> dateObserver = message -> System.out.println("The date is: " + message);
Observer<Temporal> dateTimeObserver = message -> {
if (message instanceof LocalDateTime) {
System.out.println("The date/time is: " + message);
}
};
Observer<Temporal> generalObserver = message -> System.out.println("Now is: " + message);
SimpleObservable<Temporal> clock = new SimpleObservable<>();
clock.subscribe(timeObserver, temporal -> temporal instanceof LocalTime);
clock.subscribe(dateObserver, temporal -> temporal.getClass().getSimpleName().equals("LocalDate"));
clock.subscribe(dateTimeObserver); // does its own filtering
clock.subscribe(generalObserver); // no filtering
clock.notifyObservers(LocalDate.now());
clock.notifyObservers(LocalTime.now());
clock.notifyObservers(LocalDateTime.now());
clock.notifyObservers(OffsetDateTime.now());

输出:

Now is: 2021-07-13
The date is: 2021-07-13
The time is: 11:37:05.997223
Now is: 11:37:05.997223
Now is: 2021-07-13T11:37:05.997319
The date/time is: 2021-07-13T11:37:05.997319
Now is: 2021-07-13T11:37:05.997626+02:00

最新更新