浅谈设计模式之----观察者模式

     观察者模式也是我们日常程序编写中碰到比较多的一种设计模式。首先,所谓观察者模式定义就是指:在对象之间定义了一对多的依赖,这样一来,当一个对象的状态发生变化的时候,依赖它的多个对象都会收到通知并且自动更新。
     平时的运用中,我们一般用到Observer pattern的实现方式主要是:自定义主题(Subject)和Observer(观察者)和JDK自己封装的java.util.Observer和java.util.Observable(类似subject)来实现的。在这里,我主要讲述自定义的Observer pattern的实现吧。
     以下以气象预报站(WeatherStation)进行天气的预报为例子。气象站的需求是建立三块公布版,一块是当前气象预报(CurrentConditionDisplay)公布版、静态预报(StatisticDisplay)公布版、预报(ForeCastDisplay)公布版。其中主题的实现是气象站的数据提供(WeatherData)实现Subject(主题),观察者为Observer和DisplayElement两个接口。其中观察者的实现有三个,分别对应三块公布版。CurrentConditionDisplay、StatisticDisplay、ForestCastDisplay,散者均需要实现Observer和DisplayElement三个接口。从而,主题的实现类WeatherData通过调用观察者的接口通知观察者及时更新,观察者通过主题接口来向主题注册,在设计的过程中,会变的只是主题的状态和观察者的数目和类型。此模式可以改变依赖主题状态的对象而不该变主题的状态。
  以下是代码的实现
package com.clark.observerpattern.subject;

import com.clark.observerpattern.observer.Observer;

/**
 * 气象站主题,其对应着多个Observer对象
 * @author Administrator
 *
 */
public interface Subject {
    //注册一个Observer
    public void registerObserver(Observer obj);
    //remove一个Observer
    public void removeObserver(Observer obj);
    //当主题对象发生改变的时候,通知所有的Observer
    public void notifyAllObserver();
}

package com.clark.observerpattern.observer;
/**
 * defination much observer object
 * @author Administrator
 *
 */
public interface Observer {
    //defined a update method,parameter include temp,humidity,pressure
    public void update(float temp,float humidity,float pressure);
}
package com.clark.observerpattern.observer;
/**
 * display 布告板的信息
 * @author Administrator
 *
 */
public interface DisplayElement {
    void display();
}

package com.clark.observerpattern;

import com.clark.observerpattern.observer.DisplayElement;
import com.clark.observerpattern.observer.Observer;
import com.clark.observerpattern.subject.Subject;

class CurrentConditionsDisplay implements Observer, DisplayElement {
    private float temp;
    private float humidity;
    private Subject weatherData;
    @Override
    public void display() {
        System.out.println("current conditions:"+temp+" F degrees and "+humidity+"% humidity");
    }

@Override
    public void update(float temp, float humidity, float pressure) {
        this.temp=temp;
        this.humidity=humidity;
        display();
    }
    public CurrentConditionsDisplay(Subject weatherData){
        this.weatherData=weatherData;
        //注册改Observer,从而在后面移除的时候方便关联
        weatherData.registerObserver(this);
    }
}
package com.clark.observerpattern.observer;
import java.util.*;

import com.clark.observerpattern.subject.Subject;
import com.clark.observerpattern.subject.WeatherData;
/**
 * 统计布告板
 * @author Administrator
 *
 */
public class StatisticsDisplay implements Observer, DisplayElement {
    private float maxTemp = 0.0f;
    private float minTemp = 200;
    private float tempSum= 0.0f;
    private int numReadings;
    private Subject weatherData;

public StatisticsDisplay(WeatherData weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

public void update(float temp, float humidity, float pressure) {
        tempSum += temp;
        numReadings++;

if (temp > maxTemp) {
            maxTemp = temp;
        }
 
        if (temp < minTemp) {
            minTemp = temp;
        }

display();
    }

public void display() {
        System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings)
            + "/" + maxTemp + "/" + minTemp);
    }
}

package com.clark.observerpattern.observer;

import com.clark.observerpattern.subject.Subject;
import com.clark.observerpattern.subject.WeatherData;

/**
 * 天气预报布告板的现场预报板块
 * @author Administrator
 *
 */
public class ForecastDisplay implements DisplayElement, Observer {
    private float currentPressure = 29.92f;  
    private float lastPressure;
    private Subject weatherData;
    
    public ForecastDisplay(WeatherData weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

public void update(float temp, float humidity, float pressure) {
        lastPressure = currentPressure;
        currentPressure = pressure;
        display();
    }

public void display() {
        System.out.print("Forecast: ");
        if (currentPressure > lastPressure) {
            System.out.println("Improving weather on the way!");
        } else if (currentPressure == lastPressure) {
            System.out.println("More of the same");
        } else if (currentPressure < lastPressure) {
            System.out.println("Watch out for cooler, rainy weather");
        }
    }

}
package com.clark.observerpattern.subject;

import java.util.ArrayList;

import com.clark.observerpattern.observer.Observer;

/**
 * 模拟气象站的具体主题Subject
 * @author Administrator
 *
 */
public class WeatherData implements Subject {
    private ArrayList observers;
    private float temp;
    private float humidity;
    private float pressure;
    public WeatherData() {
        observers=new ArrayList();
    }
    @Override
    public void registerObserver(Observer obj) {
        observers.add(obj);
    }

@Override
    public void removeObserver(Observer obj) {
        int i=observers.indexOf(obj);
        if(i>=0){
            observers.remove(i);
        }
    }

@Override
    public void notifyAllObserver() {
        for (int i = 0; i < observers.size(); i++) {
            Observer o=(Observer) observers.get(i);
            o.update(temp, humidity, pressure);
        }
    }
    //当从气象站获取更新数据的时候,我们通知观察着
    public void measurementsChange(){
        notifyAllObserver();
    }
    //读取气象站数据
    public void setMeasurements(float temp,float humidity,float pressure){
        this.temp=temp;
        this.humidity=humidity;
        this.pressure=pressure;
        measurementsChange();
    }
}

package com.clark.observerpattern;

import com.clark.observerpattern.observer.ForecastDisplay;
import com.clark.observerpattern.observer.StatisticsDisplay;
import com.clark.observerpattern.subject.WeatherData;

/**
 * 气象站
 * @author Administrator
 *
 */
public class WeatherStation {
    public static void main(String[] args) {
        WeatherData weatherData=new WeatherData();
        //先往Subject中添加所有注册的主题
        CurrentConditionsDisplay currentDisplay=new CurrentConditionsDisplay(weatherData);
        StatisticsDisplay statistic=new StatisticsDisplay(weatherData);
        ForecastDisplay foreCast=new ForecastDisplay(weatherData);
        //再调用方法从主题中获取数据,从而在布告板中及时显示
        weatherData.setMeasurements(50, 80, 66);
        weatherData.setMeasurements(48, 80, 67);
        weatherData.setMeasurements(52, 80, 65);
    }
}

[置顶] head first 设计模式之----Observer pattern的更多相关文章

  1. 设计模式 - 观察者模式(Observer Pattern) Java内置 用法

    观察者模式(Observer Pattern) Java内置 用法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26601659 ...

  2. 设计模式-观察者模式(Observer Pattern)

    观察者模式(Observer Pattern):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己. 观察者 ...

  3. 设计模式 - 观察者模式(Observer Pattern) 详细说明

    观察者模式(Observer Pattern) 详细说明 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...

  4. 设计模式 - 观察者模式(Observer Pattern) 详细解释

    观察者模式(Observer Pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...

  5. [置顶] 我的设计模式学习笔记------>Java设计模式总概况

    设计模式的概念最早起源于建筑设计大师Alexander的<建筑的永恒方法>一书,尽管Alexander的著作是针对建筑领域的,但是他的观点实际上用用于所有的工程设计领域,其中也包括软件设计 ...

  6. C#设计模式——观察者模式(Observer Pattern)1

    一.概述在软件设计工作中会存在对象之间的依赖关系,当某一对象发生变化时,所有依赖它的对象都需要得到通知.如果设计的不好,很容易造成对象之间的耦合度太高,难以应对变化.使用观察者模式可以降低对象之间的依 ...

  7. C#设计模式——观察者模式(Observer Pattern)

    一.概述在软件设计工作中会存在对象之间的依赖关系,当某一对象发生变化时,所有依赖它的对象都需要得到通知.如果设计的不好,很容易造成对象之间的耦合度太高,难以应对变化.使用观察者模式可以降低对象之间的依 ...

  8. 设计模式之 Observer Pattern 观察者模式

    1.Subject通过一个容器保存零到多个Observer. 2.Subject通过Add,Delete方法调整Observer. 3.Subject的notifyObservers方法实际是逐个调用 ...

  9. 23种设计模式--观察者模式-Observer Pattern

    一.观察者模式的介绍      观察者模式从字面的意思上理解,肯定有两个对象一个是观察者,另外一个是被观察者,观察者模式就是当被观察者发生改变得时候发送通知给观察者,当然这个观察者可以是多个对象,在项 ...

随机推荐

  1. 安装Devstack的DNS问题

    所谓的OpenStack一键安装,省去了敲键盘的麻烦,但是卡在中间出了问题也是比较尴尬的 在公司内安装经常会出现卡在下载软件的地方,有时候还会出错 trick就是换一个US的dns,比如8.8.8.8

  2. Cocos2d-x 3.0final手机游戏开发视频教程2014 - 自学编程 -(陆续更新中)

    内容: 非常多人问我:沈老师,要不要更新引擎版本号到3.0,更新这么快,以后会不会每一个月都有一次,好怕呀. 我说:无论你曾经是哪个版本号,3.0final是一个架构级别的升级,能够在新项目中果断升级 ...

  3. BZOJ 2038: [2009国家集训队]小Z的袜子(hose) ( 莫队 )

    莫队..先按sqrt(n)分块, 然后按块的顺序对询问排序, 同块就按右端点排序. 然后就按排序后的顺序暴力求解即可. 时间复杂度O(n1.5) --------------------------- ...

  4. Java--格式化输出

    Java的格式化输出等同于String.Format,与C有很大的相似,比如 System.out.printf("%8.2f", x); 在printf中,可以使用多个参数,例如 ...

  5. 演练5-2:Contoso大学校园管理2

    一.添加列标题排序功能 我们将增加Student/Index页面的功能,为列标题添加超链接,用户可以点击列标题对那一列进行排序. 1.修改Index方法 public ActionResult Ind ...

  6. BZOJ 3173: [Tjoi2013]最长上升子序列( BST + LIS )

    因为是从1~n插入的, 慢插入的对之前的没有影响, 所以我们可以用平衡树维护, 弄出最后的序列然后跑LIS就OK了 O(nlogn) --------------------------------- ...

  7. 配置用户范围settings.xml

    Maven用户可以选择配置<<MavenHome>>/conf/settings.xml或者<<UserHome>>/.m2/settings.xml. ...

  8. 基于visual Studio2013解决C语言竞赛题之1087数字变换

        题目 解决代码及点评 /************************************************************************/ /* ...

  9. css3 动画运动路径

    1.cubic-bezier贝塞尔曲线CSS3动画工具 http://www.xuanfengge.com/cubic-bezier-bezier-css3-animation-tools.html ...

  10. 一点一滴完全突破KAZE特征检测算法,从各向异性扩散滤波开始(1)

    ECCV2012中出现了一种比SIFT更稳定的特征检测算法KAZE.尽管,这个算法是几个法国人提出的,但是算法却有一个日文的名字.KAZE是日语‘风’的谐音,最近宣布退休的宫崎骏所拍摄的影片“起风了” ...