设计模式学习——观察者模式(Observer Pattern)
2015-09-16 08:27
796 查看
0. 前言
观察者模式在许多地方都能够用到,特别是作为MVC模式的一部分,在MVC中,模型(M):存放数据,视图(V):显示数据。当模型中的数据发生改变时,视图会得到通知,这是典型的观察者模式。
1. 定义
观察者模式:定义了一对多的关系,一个对象作为主题,它维护了一系列的依赖对象,当主题的状态发生改变时,会自动地通知依赖对象(通常通过调用依赖对象的方法来实现)。
官方定义:wiki
2. 应用
这里通过《Head first 设计模式》中的例子来实现观察者模式。这里有一个气象数据和公布栏,当气象数据发生改变时,会通知公布栏,使其更新数据。
源码:
主题Subject接口:
观察者Observer接口
气象数据实现:
显示接口:
公布栏实现:
3. JDK中Observable类分析
在JDK中提供了Observable类以及Observer接口方便实现观察者模式,但是这里的主题是Observable是一个类,需要通过继承来实现,所以很大的限制了它的使用。
Observable类的添加观察者方法,通过synchronized实现同步,其Observable内部维护着一个Vector容器,用于存放观察者对象。
通知函数,这里会判断一个标识,所以在调用通知时需要先调用 setChanged 方法,然后将其观察者保存到一个数组中,这里会有一个问题,即当调用删除一个观察者的时候,如果正在调用notifyObservers时,依然会通知到被删除的观察者。对于添加来说也是一样的,会错过这一次的通知。
观察者模式在许多地方都能够用到,特别是作为MVC模式的一部分,在MVC中,模型(M):存放数据,视图(V):显示数据。当模型中的数据发生改变时,视图会得到通知,这是典型的观察者模式。
1. 定义
观察者模式:定义了一对多的关系,一个对象作为主题,它维护了一系列的依赖对象,当主题的状态发生改变时,会自动地通知依赖对象(通常通过调用依赖对象的方法来实现)。
官方定义:wiki
2. 应用
这里通过《Head first 设计模式》中的例子来实现观察者模式。这里有一个气象数据和公布栏,当气象数据发生改变时,会通知公布栏,使其更新数据。
源码:
主题Subject接口:
package ObserverPattern; public interface Subject { public void registerObserver( Observer observer ); public void removeObserver( Observer observer ); public void notifyObservers(); }
观察者Observer接口
package ObserverPattern; public interface Observer { public void update(Object obj); }
气象数据实现:
package ObserverPattern; import java.util.ArrayList; import java.util.Iterator; public class WeatherData implements Subject { private ArrayList<Observer> observers = null; private double temperature; private double humidity; private double pressure; public WeatherData( ) { observers = new ArrayList<>(); } public double getTemperature() { return temperature; } public double getHumidity() { return humidity; } public double getPressure() { return pressure; } public void SetWeather( double temperature, double humidity, double pressure ) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; mesurementsChanged(); } public void mesurementsChanged() { notifyObservers(); } @Override public void registerObserver(Observer observer) { observers.add(observer); } @Override public void removeObserver(Observer observer) { observers.remove(observer); } @Override public void notifyObservers() { for ( Iterator<Observer> iterator = observers.iterator(); iterator.hasNext(); ) { Observer observer = (Observer) iterator.next(); observer.update(this); } } }
显示接口:
package ObserverPattern; public interface DisplayBoard { public void display(); }
公布栏实现:
package ObserverPattern; public class CurrentWeatherBoard implements Observer, DisplayBoard { private double temperature; public CurrentWeatherBoard( Subject subject ) { subject.registerObserver(this); } @Override public void update(Object obj) { if ( obj instanceof WeatherData ) { WeatherData weatherData = (WeatherData)obj; this.temperature = weatherData.getTemperature(); display(); } } @Override public void display() { System.out.println(this.getClass().getName() + ":" + this.temperature); } }
3. JDK中Observable类分析
在JDK中提供了Observable类以及Observer接口方便实现观察者模式,但是这里的主题是Observable是一个类,需要通过继承来实现,所以很大的限制了它的使用。
Observable类的添加观察者方法,通过synchronized实现同步,其Observable内部维护着一个Vector容器,用于存放观察者对象。
public synchronized void addObserver(Observer o) { if (o == null) throw new NullPointerException(); if (!obs.contains(o)) { obs.addElement(o); } }
通知函数,这里会判断一个标识,所以在调用通知时需要先调用 setChanged 方法,然后将其观察者保存到一个数组中,这里会有一个问题,即当调用删除一个观察者的时候,如果正在调用notifyObservers时,依然会通知到被删除的观察者。对于添加来说也是一样的,会错过这一次的通知。
public void notifyObservers(Object arg) { Object[] arrLocal; synchronized (this) { if (!changed) return; arrLocal = obs.toArray(); clearChanged(); } for (int i = arrLocal.length-1; i>=0; i--) ((Observer)arrLocal[i]).update(this, arg); }
相关文章推荐
- 链表
- 为什么构造函数不能为虚函数
- iOS 学习总结----音频/视频处理
- Scala中隐式对象代码实战详解之Scala学习笔记-54
- Divide Two Integers
- Text Justification
- Max Points on a Line
- asp.net服务器控件button先执行js再执行后台的方法
- Spiral Matrix II
- ZigZag Conversion
- C++: 主要知识点
- 研究生开题报告需要注意的几点
- Spiral Matrix
- UI高级第二课  多线程和GCD——iOS学习连载30
- Pascal’s Triangle II
- UI高级第一课  block语法——iOS学习连载29
- Redis 学习笔记1
- LeetCode-Contains Duplicate II
- 单位和值
- C# 初步学习