模式的秘密——观察者模式
一、 观察者模式的定义
定义对象间的一种一对多的依赖关系。当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
二、 认识观察者模式
1、 目标与观察者之间的关系
目标与观察者之间是一对多的关系,当然观察者只有一个也是合理的。
2、 单向依赖
观察者和目标是单向依赖的关系,只有观察者依赖目标,而不是目标依赖观察者,只有目标知道什么时候通知观察者,整个过程中观察者都是被动的,被动的等待目标的通知。
3、 命名建议
第一,目标接口的定义,建议在名称后面跟上Subject;
第二,观察者接口的定义,建议在名称后面跟上Observer;
第三,观察者接口的更新方法,建议名称为update,参数可以根据需要自己定义。
4、 触发通知的时机
一般情况是在完成状态维护后触发通知,因为通知会传递数据,不能够先通知再改变数据。
5、 观察者模式的调用顺序示意图
6、 通知的顺序
多个观察者之间的通知顺序是不确定的,彼此之间是平行的,观察者之间不应该有相互依赖的关系。
三、 观察者模式的实例
我们以天气状况为例,不同的观察者会根据天气情况选择做不同的事情。
1、 首先,我们需要定义观察者接口,Observer.java
/*
* 观察者接口,定义一个更新的接口给那些在目标发生改变的时候被通知的对象
*/
public interface Observer{
/*
* 更新的接口
* @param subject 传入目标对象,方便获取相应的目标对象的状态
*/
public voidupdate(WeatherSubject subject);
}
2、 接下来,我们定义观察者的构造类,并实现观察者接口
/*
* 具体的观察者对象,实现更新的方法,使自身的状态和目标的状态保持一致
*/
public class ConcreteObserverimplements Observer {
// 观察者的名字
private String observerName;
// 天气内容的情况,这个消息从目标处获取
private String weatherContent;
// 提醒的内容
private String remindThing;
public String getObserverName() {
return observerName;
}
public voidsetObserverName(String observerName) {
this.observerName = observerName;
}
public String getWeatherContent() {
return weatherContent;
}
public voidsetWeatherContent(String weatherContent) {
this.weatherContent = weatherContent;
}
public String getRemindThing() {
return remindThing;
}
public voidsetRemindThing(String remindThing) {
this.remindThing = remindThing;
}
/*
* 获取目标类的状态同步到观察者的状态中 (non-Javadoc)
*
* @see Observer#update(Subject)
*/
@Override
public voidupdate(WeatherSubject subject) {
weatherContent = ((ConcreteWeatherSubject) subject).getWeatherContent();
System.out.println(observerName + "收到了" + weatherContent + "," + remindThing);
}
}
3、 然后,我们需要定义目标对象,我们以天气作为目标对象
import java.util.ArrayList;
import java.util.List;
/*
* 目标对象,它知道观察它的观察者,并提供注册(添加)和删除观察者的接口
*/
public class WeatherSubject {
// 用来保存注册的观察者对象
privateList<Observer> observers = new ArrayList<>();
// attachdetach notifyObservers
/*
* 把订阅天气的人添加到订阅者列表中
*/
publicvoid attach(Observer observer) {
observers.add(observer);
}
/*
* 删除集合中的指定订阅天气的人
*/
publicvoid detach(Observer observer) {
observers.remove(observer);
}
/*
* 通知所有注册的观察者对象
*/
protectedvoid notifyObservers() {
for(Observerobserver: observers){
observer.update(this);
}
}
}
4、 接着就是目标对象的构