设计模式学习笔记之观察者模式
观察者模式
定义了对象之间的一对多依赖,这样一来,当一个对象状态改变时,它的所有依赖者都会收到通知并自动更新。
观察者模式中,分为推和拉两种模式。
推模式,即主题对象向观察者对象推送状态值,不管观察者对象是否需要,并且推送全部数据或者部分数据。
拉模式,即主题对象通知观察者对象状态值已改变,观察者根据自己需要决定是否主动到主体对象中获取详细信息。
两种模式的比较
1、推模型是假定主题对象知道观察者需要的数据;而拉模型是主题对象不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传递给观察者,让观察者自己去按需要取值。
2、推模型可能会使得观察者对象难以复用,因为观察者的update()方法是按需要定义的参数,可能无法兼顾没有考虑到的使用情况。这就意味着出现新情况的时候,就可能提供新的update()方法,或者是干脆重新实现观察者;而拉模型就不会造成这样的情况,因为拉模型下,update()方法的参数是主题对象本身,这基本上是主题对象能传递的最大数据集合了,基本上可以适应各种情况的需要。
说明:
1、观察者模式将观察者和主题(被观察者)的对象分离开,实现了两者的松耦合。提高了应用程序的可维护性和重用性;
2、JAVA API 内置有观察者模式。位于java.util包,包含有最基本的Observer接口与Observable类,分别对应观察者和主题;
3、主题仅需要把实时的状态值更新给观察者即可,而不需要知道观察者怎样处理数据或者其他细节。
场景:
1、对于一个对象的状态值需要实时更新到其他任何几个对象。如气象站检测的天气数据,要实时更新给气象网站的布告板。
/**
* 主题类接口。
* 用来定义注册观察者、移除观察者、通知更新等方法
* @author xiabaike
*/
public interface Subject {
/**
* 注册观察者
* */
public void registerObserver(Observer o);
/**
* 移除观察者
* */
public void removeObserver(Observer o);
/**
* 当状态改变时,调用此方法,通知所有观察者
* */
public void notifyObservers();
}
|
/**
* 观察者类接口。
* 当主题状态发生改变时,主题会把这些状态值当做方法的参数,传送给观察者。
* @author xiabaike
* */
public interface Observer {
/**
* 当主题状态发生改变时,主题会把这些状态值当做方法的参数,传送给观察者
* 所有观察者都必须实现此方法,以实现观察者接口
* */
public void update(float temp, float humidity, float pressure);
}
|
/**
* 展示。在布告板上显示内容
* */
public interface DisplayElement {
/**
* 当布告板需要显示时,调用此方法
* */
public void display();
}
|
/**
* 天气数据类。产生更新状态值,并通知布告板观察者
* */
public class WeatherData implements Subject{
// 用来存放所有的观察者
private List<Observer> observerList;
private float tempPerature;
private float humidity;
private float pressure;
public WeatherData() {
observerList = new ArrayList<Observer>();
}
public void registerObserver(Observer o) {
observerList.add(o);
}
public void removeObserver(Observer o) {
if(observerList.contains(o)) {
observerList.remove(o);
}
}
public void notifyObservers() {
for(int i = 0; i < observerList.size(); i++) {
observerList.get(i).update(tempPerature, humidity, pressure);
}
}
/**
* 当从气象站得到更新观测值时,通知观察者
* */
public void setMeasurements(float temperature, float humidity, float pressure) {
this.tempPerature = temperature;
this.humidity = humidity;
this.pressure = pressure;
notifyObservers();
}
}
|
/**
* 具体布告板实现类。获取状态值,并展示
* */
public class CurrentConditionsDisplay implements Observer, DisplayElement{
private float tempPerature;
private float humidity;
private float pressure;
private Subject subject;
public CurrentConditionsDisplay(Subject subject) {
this.subject = subject;
this.subject.registerObserver(this);
}
public void update(float temp, float humidity, float pressure) {
this.tempPerature = temp;
this.humidity = humidity;
this.pressure = pressure;
display();
}
public void display() {
System.out.println("Current conditions: " + tempPerature +", "+ humidity +", "+ pressure);
}
}
|
/**
* 主类,模拟气象站产生检测数据,并更新给布告板
* */
public class WeatherStation {
public static void main(String[] args) {
WeatherData subject = new WeatherData();
CurrentConditionsDisplay observer = new CurrentConditionsDisplay(subject);
subject.setMeasurements(1, 2, 3);
}
}
|
参考资料:《Head First 设计模式》