观察者模式
观察者模式的定义
定义对象之间一种一对多的关系。当一个对象的状态发生改变的时候,所有依赖于它的对象都得到通知并被自动更新。
观察者模式的结构和说明
Subject: 目标对象,通常具有以下功能
- 一个目标可以被多个观察者观察
- 目标提供观察者注册和退订的维护
- 当目标的状态发生变化的时候,目标负责通知所有注册的,有效的观察者。
Observer: 定义观察者的借口,提供目标通知时对应的更新方法,这个更新方法进行相应的业务处理,可以在这个方法里面回调目标对象,翼获取目标对象的数据。
- ConcreteSubject: 具体目标实现对象,用来维护目标状态,当目标对象的状态发生改变的时候,通知所注册的,有效的观察者,让观察者执行相应的处理。
- ConcreteObserver: 观察者的具体实现对象,用来接受目标的通知,并进行相应的后续处理,比如更新自身的状态以保持和目标的相应状态一致。
观察者模式示例代码
(1) 目标对象的定义,实例代码:
public class Subject{
/**
*用来保存注册的观察者对象
*/
private List<Observer> observers = new ArrayList<Observer>();
/**
*注册观察者对象
*/
public void attach(Observer observer){
observers.add(observer);
}
/**
*删除观察者对象
*/
public void detach(Observer observer){
observers.remove(observer);
}
/**
*通知所有注册的观察者对象
*/
protected void notifyObservers(){
for(Observer observer : observers){
observer.update(this);
}
}
}
(2)具体目标对象。示例代码:
/**
* 具体的目标对象,负责把有关状态存入到相应的观察者对象
* 并在自己状态发生改变的时候,通知各个观察者
*/
public class ConcreteSubject extends Subject{
/**
* 示意,目标对象的状态
*/
private String subjectState'
public String getSubjectState(){
return subjectState;
}
public void setSubjectState(String subjectState){
this.subjectState = subjectState;
//状态发生了改变,通知哥哥观察者
this.notifyObservers();
}
}
(3)观察者的接口定义,示例代码:
/**
*观察者接口,定义一个更新的接口给那些在目标发生改变的时候被 *通知的对象
*/
public interface Observer{
public void update(Subject subject);
}
(4)观察者的具体实现,示例代码:
/**
*具体观察者对象,实现更新的方法,使自身的状态和目标的状态保持一
*致
*/
public class ConcreteObserver implements Observer{
private String observerState;
public void update(Subject subject){
//具体更新的实现
//这里可能需要更新观察者的状态,使其与目标状态一致
observerState = ((ConcreteSubject)subject).getSubjectState();
}
}
认识观察者模式
1.目标和观察者之间的关系
按照模式的定义,目标和观察者之间是典型的一对多的关系。
但是要注意,如果观察者只有一个也是可以的,这样就变相的实现了目标和观察者之间一对一的关系,这也使得在处理一个对象的状态变化影响到另一个对象的时候,也可以考虑使用观察者模式。
同样,一个观察者也可以同时观察多个目标,如果观察者为多个目标定义的更新方法都叫update的话会有问题,因为要接收多个目标的通知,如果一个update则需要在方法内部进行区分,一般观察者应该为不用的观察者定义不同的回调方法,这样实现最好。
2.单向依赖
在观察者模式中,观察者和目标是单向依赖的,只有观察者依赖于目标,而目标不会依赖于观察者。
它们之间的联系的主动权掌握在目标手中,只有目标知道什么时候需要通知观察者。在整个过程中,观察者始终是被动的,被动地等待目标的通知,等待目标传值给它。
3.具体的实现说明
- 具体的目标实现对象要能维护观察者的注册信息,最简单的实现方案就如同前面的例子那样,采用一个集合来保存观察者的注册信息。
- 具体的目标实现对象需要维护引起通知的状态,一般情况下是目标自身的状态。变形使用的情况下,也可以是别的对象的状态。
- 具体的观察者实现对象需要能接受目标的通知,能够接收目标传递的数据,或者能主动的去获取目标的数据,并进行后续的处理。
- 如果是一个观察者观察多个目标,那么在观察者的更新方法里面,需要去判断是来自哪一个目标的通知。一种简单的解决方案就是拓展update方法,比如在方法中多传递一个参数进行区分,要么直接定义多个回调方法。
4.触发通知的时机
在实现观察者模式的时候,一定要注意触发通知的时机,一般情况下,是在完成了状态的维护后触发,因为通知会传递数据,不能够先通知后改数据,这很容易出问题,会导致观察者和目标对象的状态不一致。
观察者模式的本质
观察者模式的本质:触发联动
当修改目标对象的状态的时候,就会触发相应的通知,然后会循环调用所有注册的观察者对象的相应方法,其实就是相当于联动调用这些观察者的方法。
而且这个联动还是动态的,可以通过注册和取消注册来控制观察者,因而可以在程序运行期间,通过动态的控制观察者,来变相的实现添加和删除某些功能处理,这些功能就是观察者在update的时候执行的功能。
同时目标对象和观察者对象的解耦,又保证了无论观察者发生怎样的变化,目标对象总是能够正确地联动过来。
相关模式
- 观察者模式和状态模式