设计模式 - 观察者模式(Observer Pattern) 详解

观察者模式(Observer Pattern) 详解




观察者模式(Observer Pattern): 定义了对象之间的一对多的依赖, 这样一来, 当一个对象改变状态时, 它的所有依赖者都会收到通知并自动更新.


使用方法:


1. 首先新建主题(subject)接口, 负责注册(register)\删除(remove)\通知(notify)观察者; 观察者(observer)接口, 负责更新(update)数据;

主题(subject)接口: 注册观察者(registerObserver), 删除观察者(removeObserver), 通知观察者(notifyObservers, 通知所有观察者);

观察者(observer)接口: 更新(update);


代码:

[java]  view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * @time 2014年5月22日 
  3.  */  
  4. package observer;  
  5.   
  6. /** 
  7.  * @author C.L.Wang 
  8.  * 
  9.  */  
  10. public interface Subject {  
  11.     public void registerObserver(Observer o);  
  12.     public void removeObserver(Observer o);  
  13.     public void notifyObervers();  
  14. }  
  15.   
  16.   
  17. /** 
  18.  * @time 2014年5月22日 
  19.  */  
  20. package observer;  
  21.   
  22. /** 
  23.  * @author C.L.Wang 
  24.  * 
  25.  */  
  26. public interface Observer {  
  27.     public void update(float temp, float humidity, float pressure);  
  28. }  
  29.   
  30.   
  31. /** 
  32.  * @time 2014年5月22日 
  33.  */  
  34. package observer;  
  35.   
  36. /** 
  37.  * @author C.L.Wang 
  38.  * 
  39.  */  
  40. public interface DisplayElement {  
  41.     public void display();  
  42. }  

2. 实现主题(subject)接口, 通过列表(list)的形式注册(register)和删除(remove)观察者, 

通知(notify)观察者时, 循环调用所有已注册的观察者的更新(update)动作;

通过接口函数(set), 封装通知(notify)动作, 传入参数并进行通知.


代码:

[java]  view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * @time 2014年5月22日 
  3.  */  
  4. package observer;  
  5.   
  6. import java.util.ArrayList;  
  7.   
  8. /** 
  9.  * @author C.L.Wang 
  10.  * 
  11.  */  
  12. public class WeatherData implements Subject {  
  13.       
  14.     public ArrayList<Observer> observers;  
  15.     private float temperature;  
  16.     private float humidity; //湿度  
  17.     private float pressure;  
  18.       
  19.     public WeatherData() {  
  20.         observers = new ArrayList<Observer>();  
  21.     }  
  22.       
  23.     /* (non-Javadoc) 
  24.      * @see observer.Subject#registerObserver(observer.Observer) 
  25.      */  
  26.     @Override  
  27.     public void registerObserver(Observer o) {  
  28.         // TODO Auto-generated method stub  
  29.         observers.add(o);  
  30.     }  
  31.   
  32.     /* (non-Javadoc) 
  33.      * @see observer.Subject#removeObserver(observer.Observer) 
  34.      */  
  35.     @Override  
  36.     public void removeObserver(Observer o) {  
  37.         // TODO Auto-generated method stub  
  38.         int i = observers.indexOf(o);  
  39.         if (i>=0) {  
  40.             observers.remove(i);  
  41.         }  
  42.     }  
  43.   
  44.     /* (non-Javadoc) 
  45.      * @see observer.Subject#notifyObervers() 
  46.      */  
  47.     @Override  
  48.     public void notifyObervers() {  
  49.         // TODO Auto-generated method stub  
  50.         for (int i=0; i<observers.size(); ++i) {  
  51.             Observer observer = (Observer)observers.get(i);  
  52.             observer.update(temperature, humidity, pressure);  
  53.         }  
  54.     }  
  55.       
  56.     public void measurementsChanged() {  
  57.         notifyObervers();  
  58.     }  
  59.       
  60.     public void setMeasurements(float temperature, float humidity, float pressure) {  
  61.         this.temperature = temperature;  
  62.         this.humidity = humidity;  
  63.         this.pressure = pressure;  
  64.         measurementsChanged();  
  65.     }  
  66.   
  67. }  

3. 实现观察者(observer)接口, 主要保存收到的数据, 并实现更新(update)动作, 即把数据保存在本地;

构造函数中, 把自己注册(register)入, 传入的主题(subject)参数, 使主题可以通知观察者.


代码:

[java]  view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * @time 2014年5月22日 
  3.  */  
  4. package observer;  
  5.   
  6. /** 
  7.  * @author C.L.Wang 
  8.  * 
  9.  */  
  10. public class CurrentConditionsDisplay implements Observer, DisplayElement {  
  11.       
  12.     private float temperature;  
  13.     private float humidity;  
  14.     private Subject weatherData;  
  15.       
  16.     public CurrentConditionsDisplay(Subject weatherData) {  
  17.         this.weatherData = weatherData;  
  18.         weatherData.registerObserver(this);  
  19.     }  
  20.       
  21.     /* (non-Javadoc) 
  22.      * @see observer.DisplayElement#display() 
  23.      */  
  24.     @Override  
  25.     public void display() {  
  26.         // TODO Auto-generated method stub  
  27.         System.out.println("Current conditions: " + temperature +  
  28.                 "F degrees and " + humidity + "% humidity");  
  29.     }  
  30.   
  31.     /* (non-Javadoc) 
  32.      * @see observer.Observer#update(float, float, float) 
  33.      */  
  34.     @Override  
  35.     public void update(float temperature, float humidity, float pressure) {  
  36.         // TODO Auto-generated method stub  
  37.         this.temperature = temperature;  
  38.         this.humidity = humidity;  
  39.         display();  
  40.     }  
  41.   
  42. }  
  43.   
  44.   
  45. package observer;  
  46.   
  47. import java.util.*;  
  48.   
  49. public class ForecastDisplay implements Observer, DisplayElement {  
  50.     private float currentPressure = 29.92f;    
  51.     private float lastPressure;  
  52.     private WeatherData weatherData;  
  53.   
  54.     public ForecastDisplay(WeatherData weatherData) {  
  55.         this.weatherData = weatherData;  
  56.         weatherData.registerObserver(this);  
  57.     }  
  58.   
  59.     public void update(float temp, float humidity, float pressure) {  
  60.                 lastPressure = currentPressure;  
  61.         currentPressure = pressure;  
  62.   
  63.         display();  
  64.     }  
  65.   
  66.     public void display() {  
  67.         System.out.print("Forecast: ");  
  68.         if (currentPressure > lastPressure) {  
  69.             System.out.println("Improving weather on the way!");  
  70.         } else if (currentPressure == lastPressure) {  
  71.             System.out.println("More of the same");  
  72.         } else if (currentPressure < lastPressure) {  
  73.             System.out.println("Watch out for cooler, rainy weather");  
  74.         }  
  75.     }  
  76. }  
  77.   
  78.   
  79. package observer;  
  80.   
  81. import java.util.*;  
  82.   
  83. public class StatisticsDisplay implements Observer, DisplayElement {  
  84.     private float maxTemp = 0.0f;  
  85.     private float minTemp = 200;  
  86.     private float tempSum= 0.0f;  
  87.     private int numReadings;  
  88.     private WeatherData weatherData;  
  89.   
  90.     public StatisticsDisplay(WeatherData weatherData) {  
  91.         this.weatherData = weatherData;  
  92.         weatherData.registerObserver(this);  
  93.     }  
  94.   
  95.     public void update(float temp, float humidity, float pressure) {  
  96.         tempSum += temp;  
  97.         numReadings++;  
  98.   
  99.         if (temp > maxTemp) {  
  100.             maxTemp = temp;  
  101.         }  
  102.    
  103.         if (temp < minTemp) {  
  104.             minTemp = temp;  
  105.         }  
  106.   
  107.         display();  
  108.     }  
  109.   
  110.     public void display() {  
  111.         System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings)  
  112.             + "/" + maxTemp + "/" + minTemp);  
  113.     }  
  114. }  

4. 测试, 创建不同的观察者(observer), 并把主题(subject)作为参数传入, 通知观察者.


代码:

[java]  view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * @time 2014年5月22日 
  3.  */  
  4. package observer;  
  5.   
  6. /** 
  7.  * @author C.L.Wang 
  8.  * 
  9.  */  
  10. public class WeatherStation {  
  11.   
  12.     /** 
  13.      * @param args 
  14.      */  
  15.     public static void main(String[] args) {  
  16.         // TODO Auto-generated method stub  
  17.         WeatherData weatherData = new WeatherData();  
  18.           
  19.         CurrentConditionsDisplay currentConditionsDisplay =   
  20.                 new CurrentConditionsDisplay(weatherData); //new的时候进行注册  
  21.           
  22.         StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);  
  23.         ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);  
  24.           
  25.         weatherData.setMeasurements(806530.4f);  
  26.         weatherData.setMeasurements(827029.2f);  
  27.         weatherData.setMeasurements(789029.2f);  
  28.     }  
  29.   
  30. }  

5. 输出:

[java]  view plaincopy在CODE上查看代码片派生到我的代码片
  1. Current conditions: 80.0F degrees and 65.0% humidity  
  2. Avg/Max/Min temperature = 80.0/80.0/80.0  
  3. Forecast: Improving weather on the way!  
  4. Current conditions: 82.0F degrees and 70.0% humidity  
  5. Avg/Max/Min temperature = 81.0/82.0/80.0  
  6. Forecast: Watch out for cooler, rainy weather  
  7. Current conditions: 78.0F degrees and 90.0% humidity  
  8. Avg/Max/Min temperature = 80.0/82.0/78.0  
  9. Forecast: More of the same  


面向对象的原则:

为了交互对象之间的松耦合设计而努力.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值