zoukankan      html  css  js  c++  java
  • 第二式 观察者模式

    观察者模式

    一 气象站应用项目

      这天公司接到一个气象站项目,气象站通过自己的各类检测器获得的数据打包提供给我们,我们来帮他们实现在不同的布告板上展示,可以显示目前状况,气象统计及简单预报。并且还希望我们能公布一组API,好让其他的开发者写出自己的布告板。

      项目概况:我们建立一个应用,利用WeatherData对象取得数据,并更新三个布告板:目前情况、气象统计和天气预报。

      

    二 认识观察者模式

      在开始着手上面的项目前,我们来认识一下观察者模式。相信大家都有过订阅报纸或者订牛奶的经历,我们来看看是怎么个过程。

      首先,报社的任务是出版报纸,用户向报社订阅报纸,只要他们有新报纸出版就会送给你,如果你不想看了,取消订阅,他们就不会再送了;只要报社还没破产倒闭就一直存在订阅和取消订阅的行为。

      出版者 + 订阅者 = 观察者模式。观察者模式中出版者称作主题,订阅者称作观察者

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

      UML图如下:

       

      设计原则:为了交互对象之间的松耦合设计而努力。

      观察者模式提供了一种对象设计,让主题和观察者之间松耦合。关于观察者的一切,主题只知道他实现了观察者接口,主题不知道他具体是谁,做了哪些细节上的事。

      我们可以在任何时候增加新的观察者,而不需要修改主题的代码;同样也可以删掉旧的观察者。我们可以在其他地方独立的复用主题或观察者,因为他们之间并非紧耦合。

      松耦合的设计之所以能让我们建立弹性的OO系统,能够应对变化,是因为对象之间的相互依赖降到了最低。

    三 气象站代码实现

      UML类图:

      

      代码:

      1.创建主题、观察者、布告展示接口;天气数据封装到Data类

     1 public interface Subject {
     2     public void registerObserver(Observer o);
     3     public void removeObserver(Observer o);
     4     public void notifyObservers();
     5 }
     6 public interface Observer {
     7     public void update(Data data);
     8 }
     9 
    10 public interface DisplayElement {
    11     public void display();
    12 }
    13 public class Data {
    14     private float temp;
    15     private float humidity;
    16     private float pressure;
    17 
    18     public Data(float temp, float humidity, float pressure) {
    19         this.temp = temp;
    20         this.humidity = humidity;
    21         this.pressure = pressure;
    22     }
    23 
    24     @Override
    25     public String toString() {
    26         return "Data{" +
    27                 "temp=" + temp +
    28                 ", humidity=" + humidity +
    29                 ", pressure=" + pressure +
    30                 '}';
    31     }
    32 
    33     public float getTemp() {
    34         return temp;
    35     }
    36 
    37     public void setTemp(float temp) {
    38         this.temp = temp;
    39     }
    40 
    41     public float getHumidity() {
    42         return humidity;
    43     }
    44 
    45     public void setHumidity(float humidity) {
    46         this.humidity = humidity;
    47     }
    48 
    49     public float getPressure() {
    50         return pressure;
    51     }
    52 
    53     public void setPressure(float pressure) {
    54         this.pressure = pressure;
    55     }
    56 }

      

      2.实现主题接口的天气数据主题类

     1 public class WeatherData implements Subject{
     2     private List<Observer> list;
     3     private Data data;
     4 
     5     public WeatherData(){
     6         list = new ArrayList<Observer>();
     7     }
     8 
     9     public void registerObserver(Observer o) {
    10         //注册观察者时,将观察者添加到list中
    11         list.add(o);
    12     }
    13 
    14     public void removeObserver(Observer o) {
    15         //观察者取消订阅时
    16         list.remove(o);
    17     }
    18 
    19     public void notifyObservers() {
    20         //通知所有已注册观察者
    21         for(Observer o : list){
    22             o.update(data);
    23         }
    24     }
    25 
    26     public void dataChanged(){
    27         //气象站数据变更后,通知观察者
    28         this.notifyObservers();
    29     }
    30 
    31     public void setData(Data data){
    32         this.data = data;
    33         dataChanged();
    34     }
    35 }

       3.两种布告板观察者

     1 public class CurrentConditionDisplay implements Observer,DisplayElement {
     2     private Subject weatherData;
     3     private Data data;
     4 
     5     public CurrentConditionDisplay(Subject weatherData){
     6         this.weatherData = weatherData;
     7         weatherData.registerObserver(this);
     8     }
     9     public void display() {
    10         System.out.println("CurrentConditionDisplay:"+this.data);
    11     }
    12 
    13     public void update(Data data) {
    14         this.data = data;
    15         display();
    16     }
    17 }
    18 public class StaticsDisplay implements Observer,DisplayElement {
    19     private Subject weatherData;
    20     private Data data;
    21 
    22     public StaticsDisplay(Subject weatherData){
    23         this.weatherData = weatherData;
    24         weatherData.registerObserver(this);
    25     }
    26     public void display() {
    27         System.out.println("StaticsDisplay:"+this.data);
    28     }
    29 
    30     public void update(Data data) {
    31         this.data = data;
    32         display();
    33     }
    34 }
      4.测试类
    1 public class Test {
    2     public static void main(String[] args){
    3         WeatherData weatherData = new WeatherData();
    4         CurrentConditionDisplay display1 = new CurrentConditionDisplay(weatherData);
    5         StaticsDisplay display2 = new StaticsDisplay(weatherData);
    6         weatherData.setData(new Data(12,22,33.1f));
    7         weatherData.setData(new Data(2.3f,42,13));
    8     }
    9 }

      5.测试结果如下

      

     四 Java内置的观察者模式

      现在,都是主题数据有更新时,一股脑把所有数据都传给观察者了,观察者可能不需要这么多数据,他可能想自己来拉取数据。我们来看看java内置的观察者模式。

      Java内置的观察者模式运作方式,和我们在气象站中的实现类似,但有一些小差异。最明显的差异是WeatherData现在扩展自Observable类,并继承到一些增加,删除,

      通知观察者的方法。Observable类中,有一个setChanged方法,及changed标志,通过这些可以让主题更灵活的选择是否向观察者发送数据。







  • 相关阅读:
    layer 弹出在 iframe内部弹出不居中是原因
    关于 DropDownList 循环绑定中遇到的问题
    C# Oracle insert 过程中出现中文乱码问题
    使用C#实现sql server 2005 和Oracle 数据同步
    C# mysql 数据库操作模板
    spring jar 包详解、依赖说明
    在js中使用jstl标签给js变量赋值
    maven3 在创建web项目时:Dynamic Web Module 3.0 requires Java 1.6 or newer 错误
    hadoop start-all.sh 启动出错java.lang.ClassNotFoundException: start-all.sh
    jquery easyui datagrid 排序
  • 原文地址:https://www.cnblogs.com/bwyhhx2018/p/10658285.html
Copyright © 2011-2022 走看看