设计模式入门--观察者模式
2015-08-06 21:02
459 查看
观察者模式:定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖都会受到通知并自动更新。
优点:观察者模式提供了一种对象设计,让主题和观察者之间松耦合。改变其中一方,并不会影响另一方,使对象之间的相互依赖降到最低。
设计原则1:为了交互对象之间的松耦合设计而努力
观察者模式示例:
1.定义主题接口
/** * 主题接口 * * @author aron * */ public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObserver(); }
2.定义观察者接口
/** * 观察者接口 * * @author aron * */ public interface Observer { public void update(float temp, float humidity, float pressure); }3.定义具体主题实例类
/** * 主题实例类 * * @author aron * */ public class WeatherData implements Subject { private ArrayList<Observer> observers; private float temperature; private float humidity; private float pressure; public WeatherData() { observers = new ArrayList<Observer>(); } @Override public void registerObserver(Observer o) { observers.add(o); } @Override public void removeObserver(Observer o) { int i = observers.indexOf(o); if (i >= 0) { observers.remove(i); } } @Override public void notifyObserver() { for (Observer ob : observers) { ob.update(temperature, humidity, pressure); } } public void measureChanged() { notifyObserver(); } public void setMeasurements(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measureChanged(); } }
4.实现布告板
/** * 实现布告板 * * @author aron * */ public class CurrentConditionsDisplay implements Observer, DisplayElement { private float temperature; private float humidity; private Subject weatherData; public CurrentConditionsDisplay(Subject weatherData) { this.weatherData = weatherData; weatherData.registerObserver(this); } @Override public void display() { System.out.println("Current Conditions: " + temperature + " F degrees and " + humidity + " %humidity"); } @Override public void update(float temp, float humidity, float pressure) { this.temperature = temp; this.humidity = humidity; display(); } }5.测试
public class WeatherStation { public static void main(String[] args) { WeatherData weatherData = new WeatherData(); CurrentConditionsDisplay ccd = new CurrentConditionsDisplay(weatherData); weatherData.setMeasurements(80, 65, 30.4f); weatherData.setMeasurements(82, 70, 29.2f); weatherData.setMeasurements(78, 90, 29.2f); } }
实际上Java内置了观察者模式--java.util.Observer接口和java.util.Observable类
主题如何推送通知?
1.调用setChanged()方法,标记状态已经改变
2.调用notifyObservers()或者notifyObservers(Object arg)
观察者如何接收通知?
update(Observable o, Object arg) //可以知道来自哪个主题的通知
使用JDK的观察者模式修改如下
1. 修改WeatherData,继承Observable类
import java.util.Observable; public class WeatherDataInternal extends Observable { private float temperature; private float humidity; private float pressure; 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; } }2. 修改布告板,改变update方法
import java.util.Observable; import java.util.Observer; public class CurrentDisplayInternal implements Observer, DisplayElement { Observable observable; private float temperature; private float humidity; public CurrentDisplayInternal(Observable observable) { this.observable = observable; observable.addObserver(this); } @Override public void display() { System.out.println("Current Conditions: " + temperature + " F degrees and " + humidity + " %humidity"); } @Override public void update(Observable o, Object arg) { if (o instanceof WeatherDataInternal) { WeatherDataInternal wdi = (WeatherDataInternal) o; this.temperature = wdi.getTemperature(); this.humidity = wdi.getHumidity(); display(); } } }3.测试
public class WeatherStation { public static void main(String[] args) { WeatherData weatherData = new WeatherData(); CurrentConditionsDisplay ccd = new CurrentConditionsDisplay(weatherData); weatherData.setMeasurements(80, 65, 30.4f); weatherData.setMeasurements(82, 70, 29.2f); weatherData.setMeasurements(78, 90, 29.2f); System.out.println("=========================="); WeatherDataInternal wdi = new WeatherDataInternal(); CurrentDisplayInternal cdi = new CurrentDisplayInternal(wdi); wdi.setMeasurements(80, 65, 30.4f); wdi.setMeasurements(82, 70, 29.2f); wdi.setMeasurements(78, 90, 28.2f); } }
API缺点:
Observable是一个类,实现了notifyObservers方法,这样就会导致子类会依赖于父类的通知次序,这显然是违反松耦合的设计原则的。同时,API中setChanged()方法是protected,这就意味着出发继承该类,否则无法创建Observable实例并组合到我们自己的对象中,这也违反了“多用组合,少用继承”的设计原则。
观察者模式在JDK的JavaBeans和Swing中也都有实现,例如按钮的监听类。
相关文章推荐
- bitcask
- 如何获取XML
- Single Number
- POJ 3694 Network
- poj 2513 Colored Sticks(欧拉回路 并查集 路径压缩 字典树)(困难)
- 反向代理
- Android如何跳过小米和魅族手机对Toast的限制
- C++ 管道
- 使用存储过程实现数据库的还原与备份[转]
- rpm的使用入门
- C++ 管道
- C++ Primer 学习笔记_76_模板和泛型编程 --模板定义[继续]
- ubuntu php安装 curl扩展
- 浅谈对回调函数的理解
- 图结构练习——最小生成树 Kruskal算法
- 九度OJ 题目1032:ZOJ
- 该离开了吗?
- 连续特征离散化的好处
- 读《数学之美》第三章 统计语言模型
- uwsgi 和 flask的使用