新手发帖,很多方面都是刚入门,有错误的地方请大家见谅,欢迎批评指正
学习设计模式已经有段时光了,这是总结的第一篇博客,文中有错误、漏洞的地方,望各位支出,纠正。
视察者模式
一、基本定义
何谓视察者模式?视察者模式定义了对象之间的一对多依赖关系,这样一来,当一个对象改变状态时,它的全部依赖者都市收到通知并且自动更新。
在这里,发生改变的对象称之为视察目标,而被通知的对象称之为视察者。一个视察目标可以对应多个视察者,而且这些视察者之间没有互相联系,所以么可以根据须要增加和删除视察者,使得系统更易于扩展。
视察者模式又称为宣布-订阅模式。
二、基本结构
首先先看视察者模式的UML类图。
分析:
Subject:目标。他把全部对视察者对戏的引用保存在一个聚集里,每一个主题都可以有多个视察者。
Observer:视察者。为全部的详细视察者定义一个接口,在失掉主题的通知时可以及时的更新自己。
ConcreteSubject:详细主题。将有关状态存入详细视察者对象。在详细主题发生改变时,给全部的视察者发出通知。
ConcreteObserver:详细视察者。实现抽象视察者角色所要求的更新接口,以便使本身的状态与主题状态相协调。
三、实现视察者模式
情景是这样的:在气象观测站中,它可以追踪现在的天气状况,包含温度、适度、气压。须要实现一个布告板,可以分别显示现在的状态,气象统计和简单的预报。当气象站中获取最新的丈量数据时,三种布告板必须实时更新。
下面是这个案例的设计图:
编码实现:
主题接口 Subject.java
public interface Subject { /** * 注册视察者 * @param observer */ public void registerObserver(Observer observer); /** * 删除视察者 * @param observer */ public void removeOberver(Observer observer); /** * 当主题状态发生改变时,这个方法须要被调用,以通知全部视察者 */ public void notifyObserver(); }
视察者接口 Observer.java
public interface Observer { public void update(float temp,float humidity,float pressure); }
布告板显示接口 DisplayElement.java
public interface DisplayElement { public void display(); }
WeatherData实现主题接口 WeatherData.java
public class WeatherData implements Subject{ private List<Observer> observers; private float tempterature; private float pressure; private float humidity; public WeatherData(){ observers = new ArrayList<Observer>(); } @Override public void notifyObserver() { for(int i = 0; i < observers.size();i++){ Observer observer = observers.get(i); observer.update(tempterature, humidity, pressure); } } @Override public void registerObserver(Observer observer) { observers.add(observer); } @Override public void removeOberver(Observer observer) { int i = observers.indexOf(observer); if(i >= 0){ observers.remove(i); } } /** * 气象站失掉更新的观测数据时,通知视察者 */ public void measurementChanged(){ notifyObserver(); } public void setMeasurements(float temperature,float humidity,float pressure){ this.tempterature = temperature; this.humidity = humidity; this.pressure = pressure; measurementChanged(); } }
布告板 CurrentCondituonDisplay.java
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); //注册视察者 } public void update(float temp, float humidity, float pressure) { this.temperature = temp; this.humidity = humidity; display(); } @Override public void display() { System.out.println("Current conditions:"+temperature+"F degrees and "+humidity+"% humidity"); } }
测试程序 WeatherStation
public class WeatherStation { public static void main(String[] args) { WeatherData weatherData = new WeatherData(); CurrentConditionsDisplay conditionsDisplay = new CurrentConditionsDisplay(weatherData); weatherData.setMeasurements(80, 65, 30.4f); weatherData.setMeasurements(82, 70, 29.2f); weatherData.setMeasurements(78, 78, 40.4f); } }
运行进程
四、视察者模式的优缺点
长处:
1、当两个对象之间送耦合,他们仍然可以交互,但是不太清晰彼此的细节。视察者模式提供了一种对象设计,让主题和视察者之间送耦合。主题所晓得只是一个详细的视察者列表,每一个详细视察者都符合一个抽象视察者的接口。主题并不认识任何一个详细的视察者,它只晓得他们都有一个独特的接口。
2、视察者模式支撑“广播通信”。主题会向全部的视察者发出通知。
3、视察者模式符合“开闭准则”的要求。
缺点:
1、如果一个被视察者对象有很多的直接和间接的视察者的话,将全部的视察者都通知到会消费很多时光。
2、 如果在视察者和视察目标之间有循环依赖的话,视察目标会触发它们之间进 行循环调用,可能导致系统崩溃。
3、 视察者模式没有响应的机制让视察者晓得所视察的目标对象是怎么发生变化的,而仅仅只是晓得视察目标发生了变化。
五、视察者模式的适用场所
1、一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
2、一个对象的改变将导致其他一个或多个对象也发生改变,而不晓得详细有多少对象将发生改变,可以下降对象之间的耦合度。
3、一个对象必须通知其他对象,而并不晓得这些对象是谁。须要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用视察者模式创建一种链式触发机制。
总结
1、视察者模式定义了对象之间的一对多关系。多个视察者监听同一个被视察者,当该被视察者的状态发生改变时,会通知全部的视察者。
2、视察者模式中包含四个角色。主题,它指被视察的对象。详细主题是主题子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个视察者发出通知;视察者,将对视察主题的改变做出反响;详细视察者中维护一个指向详细目标对象的引用,它存储详细视察者的有关状态,这些状态须要和详细目标的状态保持一致。
3、主题用一个独特的接口来更新视察者。
4、视察者与被视察者之间用松耦合方法结合。
5、有多个视察者时,不可以依赖特定的通知顺序。
6、使用视察者模式,可以从被视察者处推或者拉数据。
该读书笔记的代码和部份语句均来自《Head First 设计模式》
文章结束给大家分享下程序员的一些笑话语录:
马云喜欢把自己包装成教主,张朝阳喜欢把自己包装成明星,李彦宏喜欢把自己包装成的很知性,丁磊喜欢把自己包装的有创意,李开复总摆出一副叫兽的样子。看来的。其实我想说,缺啥补啥,人之常情。