目录
前言
UML类图
观察者模式的设计要点及应用场景
观察者模式的应用
其他
前言
观察者模式也称作监听模式,即观察与被观察的关系,比如你在烧开水时看它有没有开,你就是观察者,水就是被观察者。
观察者模式是指对象之间一对多的依赖关系,每当那个特定对象改变状态时,所有依赖于它的对象都会得到通知并被自动更新。
观察者模式是对象的行为模式。有的地方称作的发布-订阅模式
、模型-视图模式
、源-监听器模式
、从属者模式
等,当你看到这种叫法时,不要觉得陌生,它们都是观察者模式。
观察者模式可以有任意多个观察者对象同时监听某一个对象。监听某个对象的叫观察者(Observer),被监听的对象叫被观察者(Subject) 。被观察者对象在内容或状态发生改变时,会通知所有观察者,使它们能自动更新自己的信息。
UML类图
观察者模式的demo代码框架可表示成如下图所示:
被观察者类中包含addObserver()
、delObserver()
、notifyObservers()
三个方法,前两个用于添加和删除观察者,后一个用于在内容或状态变化时通知所有的观察者。其代码示例如下:
public abstract class Observable {
//定义一个观察者数组
private Vector<Observer> obsVec = new Vector<Observer>();
//增加一个观察者
public void addObserver(Oberver obs)
{
this.obsVec.add(obs);
}
//删除一个观察者
public void delObserver(Observer obs)
{
this.obsVec.remove(obs);
}
//通知所有观察者
public void notifyObservers()
{
for (Observer obs:this.obsVec){
obs.update();
}
}
}
具体的被观察者有自己的业务逻辑,同时它会定义对哪些事件进行通知。其代码如下所示:
public class ObservableImpl extends Observable {
//具体的业务
public void doSomething(){
/*
do something
业务逻辑代码模块部分
*/
super.notifyObservers(); //通知部分
}
}
观察者接收到消息后,即进行update()
操作,对接收到的信息进行处理。观察者一般是一个接口,每一个实现该接口的类都是一个具体的观察者。其代码如下:
public interface Observer{
//更新方法
public void update();
}
在调用时,直接创建被观察者类和观察者类即可,如下示例:
//创建被观察者
Observable subject = new Observable ();
//创建观察者
Observer obs = new Observer();
//添加到列表
subject.addObserver(obs);
//被观察者开始动作
subject.doSomething();
观察者模式的设计要点及应用场景
在设计观察者模式时要注意以下几点:
- 要明确谁是观察者,谁是被观察者。明白了关注对象,问题也就清楚了;
-
Observable
在发送广播通知时,无须指定具体的Observer
,观察者可以自己决定是否要订阅Observable
的通知; - 被观察者至少有三个方法: 添加监听者、删除监听者和通知监听者;观察者至少有一个方法:更新方法。
观察者模式的应用场景如下:
- 一个对象的数据或状态更新需要其它对象同步更新时;
- 系统存在事件多级触发时;
- 一个对象仅需要将自己的更新通知给其它对象而不需要知道其它对象细节时,如消息推送;
- 跨系统的消息交换场景,如通信过程中的消息队列处理机制。
观察者模式的应用
观察者模式根据其侧重还可分为推模型
和拉模型
。
推模型:被观察者对象向观察者推送主题的详细信息,不管观察者是否需要,推送的信息通常是主题对象的全部或部分数据。这种模型在实现时,会把被观察者对象中的全部或部分信息通过 update 的参数传递给观察者(update(Object obj) ,通过 obj 参数传递)。
如某应用 App 的服务要在凌晨1:00开始进行维护,1:00-2:00期间所有服务将会暂停,这里你就需要向所有的 App 客户端推送完整的通知消息:“本服务将在凌晨1:00开始进行维护,1:00-2:00期间所有服务将会暂停,感谢您的理解和支持!” 不管用户想不想知道,也不管用户会不会在这段期间去访问,消息都需要被准确无误地通知到。这就是典型的推模型的应用。
拉模型:被观察者在通知观察者的时候,只传递少量关键信息。如果观察者需要更具体的信息,由观察者主动到被观察者对象中获取,相当于是观察者从被观察者对象中拉数据。这种模型在实现时,会把被观察者对象自身通过 update 方法传递给观察者(update(Observable observable ),通过 observable 参数传递)。
如某应用 App 有新的版本推出,则需要发送一个版本升级的通知消息,而这个通知消息只会简单地列出版本号和下载地址,如果你需要升级你的 App 还需要调用下载接口去下载安装包完成升级。这其实也可以理解成是拉模型。
推模型和拉模型,更多的是语义和逻辑上的区别,在代码实现的过程中,完全可以写成同时支持两种模型的通用参数形式。
观察者模式还可用于网络中的客户端和服务器,比如手机中APP
消息推送,服务端是被观察者,各手机APP
是观察者,一旦服务器有数据更新,就会被推送到客户端。只不过在这个系统中,服务器与客户端是两套完全不同的代码,它们是通过网络接口进行通讯的,因此,在学习设计模式时,应着重领悟其设计思想,而不应局限于代码层面。
下图示例了观察者模式的概括图。
其他
GOF23/ObserverMain.java at master · liuchaoOvO/GOF23 · GitHub