观察者模式归属于行为型设计模式,而行为型设计模式主要解决的是“类或对象之间的交互问题”。
观察者模式也被称为发布订阅者模式。
在 GoF 的《设计模式》一书中,它的定义是这样的:
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
翻译成中文即为:在对象间定义了一个一对多的依赖,但这个对象改变状态的时候,所有它的依赖者都会收到通知,并自动更新。
一般情况下,被依赖的对象叫作被观察者(Observable),依赖的对象叫作观察者(Observer)。但也有其他的叫法,比如:Subject-Observer、Publisher-Subscriber、Producer-Consumer、EventEmitter-EventListener、Dispatcher-Listener。
根据应用场景的不同,观察者模式会有不同的代码实现方式:
被观察者,或者可以称为事件的发送者。
根据定义,可以比较容易得出被观察者要做的事情:
interface Subject{
void registerObserver(Observer observer);
void notifyObserver(Data data);
void removeObserver(Observer observer);
}
class SubjectImpl implements Subject{
private List<Observer> observers=new ArrayList<>();
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void notifyObserver(Data data) {
for(Observer observer:observers){
observer.update(data);
}
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
}
观察者
观察者,或者可以称为事件的接收者。
当对应事件变更的时候,会收到通知并进行自动更新
interface Observer{
void update(Data data);
}
class ObserverImpl_1 implements Observer{
@Override
public void update(Data data) {
System.out.println("ObserverImpl_1,收到***" data.getData());
}
}
class ObserverImpl_2 implements Observer{
@Override
public void update(Data data) {
System.out.println("ObserverImpl_2,收到***" data.getData());
}
}
传递的数据/信息
class Data{
private String data;
Data(){
}
Data(String str){
this.data=str;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
测试/示例
public class Demo {
public static void main(String[] args) {
Observer observer_1 = new ObserverImpl_1(); // 观察者1号
Observer observer_2 = new ObserverImpl_2(); // 观察者2号
Subject subject = new SubjectImpl(); // 被观察者
subject.registerObserver(observer_1);
subject.registerObserver(observer_2);
subject.notifyObserver(new Data("数据已发送变更"));
}
}
异步非阻塞的观察者模式
如果只是做一个简单的实现,不考虑通用性、扩展性什么的,那么只需要在上述同步阻塞的观察者模式下,做些许的改动即可。有两种方案可以实现。
分析:
第一种方法会使得线程创建的数量不可控,而且过多的线程创建和销毁势必会导致性能问题。
第二种方法虽然通过线程池使得线程的数量和创建、销毁可控了。但是问题在于,其把线程池的创建、调用等逻辑耦合在了被观察者。如果项目想要复用这个异步非阻塞的观察者模式,那么势必又要在新的被观察者里添加线程池、调用线程池【重复操作】。
EventBus 框架EventBus 翻译为“事件总线”,它提供了实现观察者模式的骨架代码。基于此框架,我们可以非常容易地在自己的业务场景中实现观察者模式,不需要从零开始开发。
其中,Google Guava EventBus 就是一个比较著名的 EventBus 框架,它不仅仅支持异步非阻塞模式,同时也支持同步阻塞模式
Google Guava EventBus的github地址:https://github.com/google/guava
我自己造的轮子已经写到了个人的gitee上:https://gitee.com/shuashua-world/shuashua-blog/tree/master/造轮子/设计模式/观察者模式/EventBus/src/main/java/world/shuashua
这个轮子目前还不支持构造带有泛型参数的观察者方法,不然会出错
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved