设计模式随笔-观察者模式
2016-09-04 18:57
399 查看
观察者模式
观察者模式是JDK中使用最多的模式之一,非常有用。它是一对多关系,以及松耦合。有了观察者,你将会消息灵通。天气监测应用概况
现在有一个应用:气象监测系统。此系统中有三个部分分别是:气象站(获得实际气象数据的装置)、WeatherData对象(追踪来自气象站的数据,并更新数据)和显示器(显示目前天气状况给用户看)。
如下图所示:
需求
现在我们接受这个项目,我们的工作就是建立一个应用,利用WeatherData对象获取气象站的实时数据,并更新到显示器上面:目前状况显示器、气象统计显示器和天气预报显示器。新鲜出炉的WeatherData类
如图:measurementsChanged()方法能调用三个天气显示器实时更新数据。方法如下:
public void measurementsChanged(){ float temp = getTemperature(); float humidity = getHumidity(); float pressure = getPressure(); //分别调用三个显示器对象的update()方法更新天气显示器信息 currentConditionsDisplay.update(temp, humidity, pressure); statisticsDisplay.update(temp, humidity, pressure); forecastDisplay.update(temp, humidity, pressure); }
但是上面针对的实现编程,会导致我们以后再正价或者删除布告板是必须修改代码。改变的地方需要封装起来、针对接口编程而不针对实现编程。
认识观察者模式
就像报纸的订阅,出版商+订阅者=观察者模式。出版者=“主题”,订阅者=“观察者”
详细分析如下图:
观察者模式定义:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
观察者模式UML图如下:
观察者模式样例代码
首先是主题(Subject)接口代码:/** * 观察者模式里面的-主题 * Created by zz on 2016/8/24. */ public interface Subject { /** * 注册订阅者 * @param observer */ public void registerObserver(Observer observer); /** * 取消订阅者 * @param observer */ public void removeObserver(Observer observer); /** * 当主题状态改变时,通知所有订阅者 */ public void notifyObject(); }
订阅者(Observer)接口代码:
/** * 订阅者 * Created by zz on 2016/8/24. */ public interface Observer { public void update(float temp, float humidity, float pressure); }
WeatherData类代码实现:
public class WeatherData implements Subject { private List<Observer> observers; //订阅者 private float temperature; //温度 private float humidity; //湿度 private float pressure; //压强 public WeatherData(){ observers = new ArrayList<Observer>(); } @Override public void registerObserver(Observer observer) { observers.add(observer); } @Override public void removeObserver(Observer observer) { int i = observers.indexOf(observer); if (i > 0){ observers.remove(i); } } @Override public void notifyObject() { for (int i=0; i<observers.size(); i++){ Observer observer = observers.get(i); observer.update(temperature, humidity, pressure); } } /** * 当主题改变时调用的方法 */ public void measurementsChange(){ notifyObject(); } public void setMeasurements(float temperature, float humidity, float pressure){ this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementsChange(); } }
显示器(CurrentConditionsDisplay)类代码实现:
public class CurrentConditionsDisplay implements Observer, DisplayElement { private float temperature; //温度 private float humidity; //湿度 private Subject weatherData; public CurrentConditionsDisplay(Subject subject){ this.weatherData = subject; weatherData.registerObserver(this); } @Override public void display() { System.out.println(temperature + ":" + humidity); } @Override public void update(float temp, float humidity, float pressure) { this.temperature = temp; this.humidity = humidity; display(); } } //改变的方法提取出来 public interface DisplayElement { public void display(); }
test方法测试:
public void test(){ WeatherData weatherData = new WeatherData(); CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData); //订阅主题 weatherData.setMeasurements(80, 65, 30.4F); weatherData.setMeasurements(75, 70, 29.2F); weatherData.setMeasurements(78, 90, 29.2F); }
上面的代码我只写了一个显示天气温度的显示器类,还有其他湿度显示器等也是同样原理,只是可能计算湿度的算法不一样而已,这里就不在累赘讲述了。
JAVA内置的观察者模式
在java.util包中内含了一个叫Observer接口与Observable类,这与我们自己手动创建的Subject接口与Observer接口很相似。只是java内置的Observable是一个抽象类,而我们都用了接口来实现。下面是利用java内置的气象站OO设计:
内置的java观察者模式是如何把对象变成观察者的呢?其实和自己设计的观察者模式一样,该内置的java方法调用了Observable对象的addObserver()方法。如果不想在当观察者的话就调用该对象的removeObserver()方法。
那观察者如何收到通知呢?通过先调用Observaable对象的setChanged()方法,然后调用notifyObservers()方法通知就可以调用所有在该对象注册的观察者对象了。为什么要先调用setChanged(),这是因为内置的java观察者有一个标志位boolean change,当把标志位修改成ture时,notify方法才会执行通知。
那接收者是如何接收到通知的呢?主要是通过Observer接口的update()方法了,同自己设计的一个样:
public interface Observer { /** * This method is called whenever the observed object is changed. An * application calls an <tt>Observable</tt> object's * <code>notifyObservers</code> method to have all the object's * observers notified of the change. * * @param o the observable object. * @param arg an argument passed to the <code>notifyObservers</code> * method. */ void update(Observable o, Object arg); }
Object arg参数没有说明时可以传空。
利用内置的java观察者模式重做气象站
WeatherData代码:import java.util.Observable; /** * 内置java观察者 * Created by zz on 2016/8/24. */ public class WeatherData extends Observable { private float temperature; //温度 private float humidity; //湿度 private float pressure; //压强 public WeatherData(){} public void measurementsChanged(){ setChanged(); notifyObservers(); } public void setMeasurements(float temperature, float humidity, float pressure){ this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementsChanged(); } public float getTemperature() { return temperature; } public float getHumidity() { return humidity; } public float getPressure() { return pressure; } }
某个显示器:
import java.util.Observable; import java.util.Observer; /** * Created by zz on 2016/8/25. */ public class CurrentConditionsDisplay implements Observer, DisplayElement { private Observable observable; private float temperature; private float humidity; public CurrentConditionsDisplay(Observable observable){ this.observable = observable; observable.addObserver(this); } @Override public void display() { System.out.println("temperature:"+temperature + "humidity:"+ humidity); } @Override public void update(Observable o, Object arg) { if (o instanceof WeatherData){ WeatherData weatherData = (WeatherData) o; this.temperature = weatherData.getTemperature(); this.humidity = weatherData.getHumidity(); display(); } } }
大家可能注意到了Observable是一个类,而不是一个接口,而且它也没有实现一个接口,这样可能限制了它的使用和复用。这一点需要大家注意一下哦。
在jdk中还有挺多地方用到观察者模式的哦,比如:Swing和javaBeans中,他们都实现了观察者模式,有时间大家可以看看哟。
总结
在本章中,让我学到了一些知识:1.为交互对象之间的松耦合设计而努力。
2.观察者模式-在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新。
相关文章推荐
- 观察者模式设计--模式随笔系列:气象站的故事-观察者模式(Observer)
- 设计模式随笔系列:气象站的故事-观察者模式(Observer)[原]
- 设计模式随笔系列:气象站的故事-观察者模式(Observer)[转]
- 设计模式随笔-观察者模式
- head first 设计模式学习随笔(2)----观察者模式
- 设计模式之观察者模式 (原创)
- 设计模式之观察者模式
- 设计模式随笔系列:鸭子-策略模式(Strategy)[原]
- 设计模式与泡mm的关系之Observer观察者模式及再思考
- 设计模式之Observer观察者模式
- Java设计模式之Observer 观察者模式
- 设计模式随笔-蜡笔与毛笔的故事
- 用 spring 实现观察者设计模式
- 探究观察者设计模式
- C#中利用代理实现观察者设计模式
- 设计模式PHP5实现之----观察者(Observer)
- .NET中的设计模式五:观察者模式
- 设计模式随笔-再论锦囊妙计
- 用spring实现观察者设计模式
- IssueVision 学习笔记(三)-----设计模式之OBSERVER(观察者)模式