1.观察者模式VS监听器模式
观察者模式和监听器模式都是用于处理对象之间的通信, 但是它们之间有一些区别, 在观察者模式中, 主题对象维护了一个观察者列表, 并在主题发生变化时通知所有的观察者。观察者对象不知道其他观察者的存在, 它只知道如何更新自己。而监听器模式中, 监听器对象注册到时间源对象上, 当时间源对象发生变化时,它会通知所有住的监听器。监听器对象知道其他监听器的存在, 并且可以相互交互。因此观察者模式更适合一对多的场景, 而监听器模式更适合一对一的通信场景
2.观察者模式(发布订阅模式)
// 主题接口
public interface Subject {
// 注册观察者, 这个观察者也可以使用jdk的类
void registerObserver(Observer observer);
// 移除观察者
void removeObserver(Observer observer);
// 发布一个消息
void publishMessage(String message);
// 核心功能, 通知观察者
void notifyObservers();
}
// 具体的主题实现类
public class ConcreteSubject implements Subject{
// 观察者容器
private List<Observer> observers = new ArrayList<>();
// 发布的信息
private String message;
@Override
public void publishMessage(String message) {
this.message = message;
// 发布
notifyObservers();
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
// 观察者自己调用更新
observer.update(message);
}
}
}
// 观察者接口
public interface Observer {
void update(String message);
}
// 具体的主题实现类
public class ConcreteSubject implements Subject{
// 观察者容器
private List<Observer> observers = new ArrayList<>();
// 发布的信息
private String message;
@Override
public void publishMessage(String message) {
this.message = message;
// 发布
notifyObservers();
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
// 观察者自己调用更新
observer.update(message);
}
}
}
// 调用客户端
public class ObserverPatternExample {
public static void main(String[] args) {
// 主题对象
Subject subject = new ConcreteSubject();
// 观察者
Observer observer1 = new ConcreteObserver("observer1");
Observer observer2 = new ConcreteObserver("observer2");
// 注册观察者到主题
subject.registerObserver(observer1);
subject.registerObserver(observer2);
// 发布一个消息
subject.publishMessage("现在12点了, 我们去吃饭");
// 还有人没有到, 我们再通知一次
subject.notifyObservers();
// 观察者2请假了, 我们把他移除
subject.removeObserver(observer2);
subject.publishMessage("下午天气不好, 提前放学, 大家回家时候注意安全!!!");
}
}
输出
observer1 received message: 现在12点了, 我们去吃饭
observer2 received message: 现在12点了, 我们去吃饭
observer1 received message: 现在12点了, 我们去吃饭
observer2 received message: 现在12点了, 我们去吃饭
observer1 received message: 下午天气不好, 提前放学, 大家回家时候注意安全!!!
3.监听器模式
// 没有时间源的事件, 对应的监听器模式其实就是观察者模式
// 事件有事件源的监听器模式, 可以通过事件里的事件源, 把其他的事件对象传导给各个监听者
// 所以各个事件的监听者之间是可以相互感知的
@Getter
public class Event {
// 事件类型
private String type;
// 事件的数据
private String data;
// 事件源
private EventSource source;
public Event(String type, String data, EventSource source) {
this.type = type;
this.data = data;
this.source = source;
}
}
// 监听器接口
public interface EventListener {
// 处理监听的事件
void handleEvent(Event event);
}
// 具体的事件监听器
public class ConcreteEventListener implements EventListener{
private String name;
public ConcreteEventListener(String name) {
this.name = name;
}
@Override
public void handleEvent(Event event) {
System.out.println(name + " received event: " + event.getType() + " with data: " + event.getData());
}
}
// 事件源: 例如鼠标是一个事件源, 点击左键, 点击右键, 移动等等都是鼠标的不同事件
public class EventSource {
// 监听者对象
private List<EventListener> listeners = new ArrayList<>();
// 注册监听者
public void registerListener(EventListener listener) {
listeners.add(listener);
}
// 移除监听者
public void removeListener(EventListener listener) {
listeners.remove(listener);
}
// 事件通知
public void fireEvent(Event event) {
for (EventListener listener : listeners) {
listener.handleEvent(event);
}
}
}
public static void main(String[] args) {
// 事件源, 用来触发事件通知
EventSource source = new EventSource();
// 监听者
EventListener listener1 = new ConcreteEventListener("listener1");
EventListener listener2 = new ConcreteEventListener("listener2");
// 注册监听者
source.registerListener(listener1);
source.registerListener(listener2);
// 发布事件
source.fireEvent(new Event("greeting", "Hello World!", source));
// 移除监听者1
source.removeListener(listener1);
source.fireEvent(new Event("greeting", "Hello Again!", source));
}
}
4.总结
所以可以看出, 观察者模式和监听器模式本质是一样的,监听器模式可以看做是观察者模式的一个抽象, 两者最大的不同就是监听器模式的事件持有事件源,所以监听者可以通过事件源注册的监听对象列表, 获取到其他的监听者, 这也就是前面所说的监听者可以知道其他监听者的存在, 也是两者最本质的不同, 如果我们对发布-订阅模式(观察者模式)发布的消息也用对象把主题对象中的订阅者封装一并发布给其他订阅者, 其实此时的发布-订阅模式就和监听器模式一模一样, 但是对于发布-订阅模式而言,订阅者不应该感知到其他订阅者, 索性就有了一个监听器模式(监听器模式不一定是这样演变过来, 但是这样可以很好的帮助理解, 监听器模式本来就和交互相关联, 早期电脑就有键盘鼠标的年代, 想必监听器模式名词出现比观察者模式更早吧)