0. 前言

  观察者模式在许多地方都能够用到,特别是作为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);
}

最新文章

  1. TSql CTE 递归原理探究
  2. 如何用Endnote导入你要用的格式
  3. Openstack-Ceilometer-SNMP的使用
  4. AppInventor学习笔记(三)&mdash;&mdash;油漆桶应用学习
  5. GitLab使用方法
  6. 手机网站中 限制图片宽度 JS图片等比例缩放
  7. Js template engine
  8. (转)Spring读书笔记-----Spring核心机制:依赖注入
  9. C# foreach获取集合元素索引的坑
  10. 【JS控制图片显示的大小(图片等比例缩放)】
  11. 深度学习开发环境搭建教程(Mac篇)
  12. 【小白成长撸】--Fibonacci
  13. Unity Instantiate各函数执行顺序
  14. Docker 创建 Crowd3.3.2 以及打通 Jira Software7.12.3和Confluence6.12.2 SSO 单点登录
  15. 仿9GAG制作过程(四)
  16. CISCO MDS – Useful ‘Show’ Commands
  17. Spark DateType cast 踩坑
  18. springboot(二 如何访问静态资源和使用模板引擎,以及 全局异常捕获)
  19. BZOJ 1444 [Jsoi2009]有趣的游戏 (AC自动机 + 概率DP + Gauss)
  20. Docker一些常用命令

热门文章

  1. js 刷新windows.open另一个窗口页面或window.open的页面如何刷新(父页面)上层页面
  2. BZOJ 4384: [POI2015]Trzy wieże
  3. Leetcode 226. Invert Binary Tree
  4. bzoj3756: Pty的字符串
  5. CruiseControl.NET配置文件(生产环境版本,与SVN结合自动部署)
  6. Hash Length Extension Attacks
  7. c/c++中#和##链接符号的用法
  8. Linux下使用USB模拟ACM串口设备
  9. js调用刷新
  10. log4j属性详解