zoukankan      html  css  js  c++  java
  • 设计模式学习——观察者模式(Observer Pattern)

    0. 前言

      观察者模式在许多地方都能够用到,特别是作为MVC模式的一部分,在MVC中,模型(M):存放数据,视图(V):显示数据。当模型中的数据发生改变时,视图会得到通知,这是典型的观察者模式。

    1. 定义

      观察者模式:定义了一对多的关系,一个对象作为主题,它维护了一系列的依赖对象,当主题的状态发生改变时,会自动地通知依赖对象(通常通过调用依赖对象的方法来实现)。

      官方定义:wiki

    2. 应用

      这里通过《Head first 设计模式》中的例子来实现观察者模式。这里有一个气象数据和公布栏,当气象数据发生改变时,会通知公布栏,使其更新数据。

     

    源码:

    主题Subject接口:

    1 package ObserverPattern;
    2 
    3 public interface Subject {
    4     public void registerObserver( Observer observer );
    5     public void removeObserver( Observer observer );
    6     public void notifyObservers();
    7 }

    观察者Observer接口

    1 package ObserverPattern;
    2 
    3 public interface Observer {
    4     public void update(Object obj);
    5 }

    气象数据实现:

     1 package ObserverPattern;
     2 
     3 import java.util.ArrayList;
     4 import java.util.Iterator;
     5 
     6 public class WeatherData implements Subject {
     7 
     8     private ArrayList<Observer> observers = null;
     9     private double temperature;
    10     private double humidity;
    11     private double pressure;
    12     
    13     public WeatherData(  )
    14     {
    15         observers = new ArrayList<>();
    16     }
    17     
    18     public double getTemperature() {
    19         return temperature;
    20     }
    21 
    22     public double getHumidity() {
    23         return humidity;
    24     }
    25 
    26     public double getPressure() {
    27         return pressure;
    28     }
    29 
    30     public void SetWeather( double temperature, double humidity, double pressure )
    31     {
    32         this.temperature = temperature;
    33         this.humidity = humidity;
    34         this.pressure = pressure;
    35         mesurementsChanged();
    36     }
    37     
    38     public void mesurementsChanged()
    39     {
    40         notifyObservers();
    41     }
    42     
    43     @Override
    44     public void registerObserver(Observer observer) {
    45         observers.add(observer);
    46     }
    47 
    48     @Override
    49     public void removeObserver(Observer observer) {
    50         observers.remove(observer);
    51     }
    52 
    53     @Override
    54     public void notifyObservers() {
    55         
    56         for ( Iterator<Observer> iterator = observers.iterator();  iterator.hasNext(); ) {
    57             Observer observer = (Observer) iterator.next();
    58             observer.update(this);
    59         }
    60     }
    61 
    62 }

    显示接口:

    1 package ObserverPattern;
    2 
    3 public interface DisplayBoard {
    4     public void display();
    5 }

    公布栏实现:

     1 package ObserverPattern;
     2 
     3 public class CurrentWeatherBoard implements Observer, DisplayBoard {
     4 
     5     private double temperature;
     6     
     7     public CurrentWeatherBoard( Subject subject ) {
     8         subject.registerObserver(this);
     9     }
    10     
    11     @Override
    12     public void update(Object obj) {
    13         if ( obj instanceof WeatherData ) {
    14             WeatherData weatherData = (WeatherData)obj;
    15             this.temperature = weatherData.getTemperature();
    16             display();
    17         }
    18     }
    19 
    20     @Override
    21     public void display() {
    22         System.out.println(this.getClass().getName() + ":" +  this.temperature);
    23     }
    24 
    25 }

    3. JDK中Observable类分析

      在JDK中提供了Observable类以及Observer接口方便实现观察者模式,但是这里的主题是Observable是一个类,需要通过继承来实现,所以很大的限制了它的使用。

      Observable类的添加观察者方法,通过synchronized实现同步,其Observable内部维护着一个Vector容器,用于存放观察者对象。  

    1  public synchronized void addObserver(Observer o) {
    2         if (o == null)
    3             throw new NullPointerException();
    4         if (!obs.contains(o)) {
    5             obs.addElement(o);
    6         }
    7     }

       

      通知函数,这里会判断一个标识,所以在调用通知时需要先调用 setChanged 方法,然后将其观察者保存到一个数组中,这里会有一个问题,即当调用删除一个观察者的时候,如果正在调用notifyObservers时,依然会通知到被删除的观察者。对于添加来说也是一样的,会错过这一次的通知。

     1 public void notifyObservers(Object arg) {
     2 
     3         Object[] arrLocal;
     4 
     5         synchronized (this) {
     6             if (!changed)
     7                 return;
     8             arrLocal = obs.toArray();
     9             clearChanged();
    10         }
    11 
    12         for (int i = arrLocal.length-1; i>=0; i--)
    13             ((Observer)arrLocal[i]).update(this, arg);
    14     }
  • 相关阅读:
    【DSP开发技术】影响高性能DSP功耗的因素及其优化方法
    【DSP开发】帮您快速入门 TI 的 Codec Engine
    【DSP开发】帮您快速入门 TI 的 Codec Engine
    【DSP开发】德州仪器达芬奇五年之路七宗罪,嵌入式处理器架构之争决战2012
    【DSP开发】德州仪器达芬奇五年之路七宗罪,嵌入式处理器架构之争决战2012
    【DSP开发】DSP COFF 与 ELF文件
    【DSP开发】DSP COFF 与 ELF文件
    【DSP开发】CCS数据格式 load
    【DSP开发】CCS数据格式 load
    【DSP开发】CMD文件
  • 原文地址:https://www.cnblogs.com/jabnih/p/4811216.html
Copyright © 2011-2022 走看看