[菜鸟的设计模式之旅]观察者模式
定义:
在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新。
举例:
气象站和气象展示牌,气象站捕获到的天气数据改变后,它需要及时反馈给气象展示牌,这样就能实时展示天气数据了。那么问题来了,是“气象展示牌”不停地去get气象站里的天气数据还是应该“气象站”里数据改变的时候再通知气象展示牌改变数据呢?当然是后者更合理,这就是观察者模式,气象站相当于“主题”,而气象展示牌相当于“观察者”,当然也可以加入很多其它的“观察者”,反正气象改变的时候,“主题”会通知所有的观察者。
思路:
“主题”接口中肯定是要有三个固定方法的,“注册观察者”,“移除观察者”“通知观察者”
这时候有一个主题"气象站",它去实现“主题接口”,同时有一个“观察者”接口,毋庸置疑观察者都是要实现这个接口的。从uml图中可以看出,它们联系的桥梁就是相互依赖,简单的来说就是相互有对方的接口引用(把对方的接口类型作为自己某个方法的形参)
“主题”有了观察者的引用后,将观察者作为“注册观察者”方法的形参,加入到自己的一个list集合中(存放所有的观察者),remove观察者也是同理
而“观察者”有了“主题”的引用后,可以用主题的引用来调用主题中的注册或者移除方法,把自己(this)作为形参传进去,这样就达到了注册或者移除的目的。
它们之间有了联系之后,沟通就方便了,主题可以调用已经注册的观察者的方法,简称“通知”,主要就是遍历刚刚说的存放所有观察者的list集合,至于什么时候遍历去调用,那就看自己的业务场景了,比如本次的气象例子,可以在气象站里的气象对应属性改变的时候,去调用气象展示板里的更新方法,这就达到了最开始我们说的气象改变,立即通知气象展示板更新数据的业务。
代码
这里展示部分代码:这里我就粘贴了两个实现类的代码~
package observermode.subject; import observermode.observer.Observer; import java.util.ArrayList; 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(o); } } @Override public void notifyObservers() { for (int i = 0; i < observers.size(); i++) { Observer observer = observers.get(i); observer.update(temperature, humidity, pressure); } } public void measurementsChanged(){ notifyObservers(); } public void setMeasurements(float temperature,float humidity,float pressure){ this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementsChanged(); } }
package observermode.observer; import observermode.DisplayEelment; import observermode.subject.Subject; public class CurrentConditionsDisplay implements Observer, DisplayEelment { private float temperature; private float humidity; private Subject weatherData; public CurrentConditionsDisplay(Subject weatherData) { this.weatherData = weatherData; weatherData.registerObserver(this); } @Override public void update(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; display(); } @Override public void display() { System.out.println("现在的温度是:" + temperature); System.out.println("现在的湿度是:" + humidity); } }
参考资料:《Head First设计模式》