设计模式二之观察者模式(Subject-Observer)
观察者模式定义了一系列对象之间的一对多关系,当一个主题对象改变状态,其他所有的依赖者都会收到通知。
好了,你可能会觉得上面的描述略微复杂,较难理解,那么现在我们将用一个简单的例子去讲解这个模式。
我们先来分析出版和订阅的关系:
出版和订阅的关系:
(1) 一家出版公司,负责每天按时出版报纸
(2) 很多个用户订阅报纸,每天会收到出版社出版的报纸内容,用户可以订阅(注册),也可以取消订阅(注销注册信息)。
(3) 出版社和用户之间的关系是一(出版社)对多(用户)的关系,并且用户依赖出版社出版的报纸,以实现对自身信息数据的刷新。
(4) 我们将出版社看成主题,将用户看成观察者,整个过程就是一个 主题---观察者模式,也就是 Subject--Observer模式。
这就是最简单的观察者模式,简单理解了之后,我们来做一个气象站,需求如下:
(1) 我们需要实现一个气象站
(2) 有一个 WearherData 对象负责追踪 温度,湿度和气压的变化
(3) 有很多种不同类型(WeatherObject)的布告板,用来显示当前的天气状况,布告板必须实时更新
分析以上三个条件,可以知道 WeatherData 和 WeatherObject 存在一对多的关系,并且多个 WeatherObject 依赖 WeatherData 进行数据的刷新。
将整个过程采用观察者模式来进行分析:
接下来,我们用代码实现上面的图:
(1) 3个接口,一个Subject (主题接口), 一个 Observer(观察者接口),一个DisplayElement(布告板接口)
Subject(主题)接口:
Observer(观察者接口):
DisplayElement(布告板)接口:
(2) 实现主题(Subject)接口的WeatherData类:
public class WeatherData implements Subject{ private float tempture; private float pressure; private float humity; List<Observer> observers; public WeatherData() { observers = new ArrayList<Observer>(); } @Override public void registerObserver(Observer obv) { // TODO Auto-generated method stub //注册方法中将需要注册的观察者加到List中 observers.add(obv); } @Override public void removeObserver(Observer obv) { // TODO Auto-generated method stub //注销方法中将需要注销的观察者移除 int i = observers.indexOf(obv); if(i>=0) { observers.remove(i); } } @Override public void NotifyAllObserver() { // TODO Auto-generated method stub //通知所有观察者进行数据的刷新 for(int i=0 ;i<observers.size(); i++) { //获取到每一个观察者的对象,把该对象的所有属性值改变就行 Observer observer = (Observer)observers.get(i); observer.update(tempture, humity, pressure); } } public void SetMesurements(float tempture, float humity, float pressure) { this.humity = humity; this.pressure = pressure; this.tempture = tempture; MeasurementChanged(); } private void MeasurementChanged() { // TODO Auto-generated method stub NotifyAllObserver(); } }
(3) 现在就可以任意画自己想要的布告板了:
public class CurrentConditionDisplay implements Observer, DisplayElement { private float tempture; private float humidity; private float pressure; private Subject WeatherData; @Override public void display() { // TODO Auto-generated method stub //展示布告板 System.out.println(tempture+""+humidity+""+pressure); } @Override public void update(float temp, float humidity, float pressure) { // TODO Auto-generated method stub this.humidity = humidity; this.tempture = temp; this.pressure = pressure; display(); } public CurrentConditionDisplay(Subject weatherData) { //在构造方法中注册观察者 this.WeatherData = weatherData; WeatherData.registerObserver(this); } }
(4) 最后,写一个测试类,测试我们画好的布告板:
public class projectTestClass { public static void main(String[] args) { WeatherData weathData = new WeatherData(); CurrentConditionDisplay ss = new CurrentConditionDisplay(weathData); weathData.SetMesurements(10, 10, 10); } }
这就是整个观察者模式的处理过程。