[置顶] head first 设计模式之----Observer pattern
平时的运用中,我们一般用到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的更多相关文章
- 设计模式 - 观察者模式(Observer Pattern) Java内置 用法
观察者模式(Observer Pattern) Java内置 用法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26601659 ...
- 设计模式-观察者模式(Observer Pattern)
观察者模式(Observer Pattern):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己. 观察者 ...
- 设计模式 - 观察者模式(Observer Pattern) 详细说明
观察者模式(Observer Pattern) 详细说明 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...
- 设计模式 - 观察者模式(Observer Pattern) 详细解释
观察者模式(Observer Pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...
- [置顶] 我的设计模式学习笔记------>Java设计模式总概况
设计模式的概念最早起源于建筑设计大师Alexander的<建筑的永恒方法>一书,尽管Alexander的著作是针对建筑领域的,但是他的观点实际上用用于所有的工程设计领域,其中也包括软件设计 ...
- C#设计模式——观察者模式(Observer Pattern)1
一.概述在软件设计工作中会存在对象之间的依赖关系,当某一对象发生变化时,所有依赖它的对象都需要得到通知.如果设计的不好,很容易造成对象之间的耦合度太高,难以应对变化.使用观察者模式可以降低对象之间的依 ...
- C#设计模式——观察者模式(Observer Pattern)
一.概述在软件设计工作中会存在对象之间的依赖关系,当某一对象发生变化时,所有依赖它的对象都需要得到通知.如果设计的不好,很容易造成对象之间的耦合度太高,难以应对变化.使用观察者模式可以降低对象之间的依 ...
- 设计模式之 Observer Pattern 观察者模式
1.Subject通过一个容器保存零到多个Observer. 2.Subject通过Add,Delete方法调整Observer. 3.Subject的notifyObservers方法实际是逐个调用 ...
- 23种设计模式--观察者模式-Observer Pattern
一.观察者模式的介绍 观察者模式从字面的意思上理解,肯定有两个对象一个是观察者,另外一个是被观察者,观察者模式就是当被观察者发生改变得时候发送通知给观察者,当然这个观察者可以是多个对象,在项 ...
随机推荐
- POJ 2485:Highways(最小生成树&&prim)
Highways Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 21628 Accepted: 9970 Descrip ...
- [leetcode] Reverse Linked List 分类: leetcode 算法 2015-07-09 18:44 2人阅读 评论(0) 收藏
反转链表:比较简单的问题,可以遍历也可以递归. # Definition for singly-linked list. class ListNode: def __init__(self, x): ...
- IO操作之使用zip包压缩和解压缩文件
转自:http://www.cdtarena.com/java.htmlJava API中的import java.util.zip.*;包下包含了Java对于压缩文件的所有相关操作. 我们可以使 ...
- Qt实现不同Treewidget之间拖拽
拖拽是编程中经常要用到的,我这里主要是实习了Treewidget之间直接拖拽Item,按下Ctrl键的话是copy,不按Ctrl则是Move.以下是实现代码 class TreeItemMimeDat ...
- listview滑动
单击其中的一个item时,让这个item能滚动的listview的顶部.现在用 list.scrollTo(0, item.getTop()); 实现啦 android listview滚动到顶部 转 ...
- 转:c语言EOF是什么?(及getchar()和putchar用法)
我学习C语言的时候,遇到的一个问题就是EOF. 它是end of file的缩写,表示"文字流"(stream)的结尾.这里的"文字流",可以是文件(file) ...
- cocos2d-x2.0 win7第一次创建项目需要调用到的脚本(不断更新维护)//cocos2d-x 教程一
第一步: 最新的cocos2d-x.下载地址https://github.com/cocos2d/cocos2d-x github上最新的引擎,值得注意的是官网上发布的引擎是稳定版.选择哪种就看个人喜 ...
- WinForm - ListView点击空白事件
有时看似很小的一个问题却可能困扰我们许久,比如ListView这个问题,其Click事件只是在有选中项的时候才触发,点击其空白处(无选中项)是不会触发Click事件的,找了许久才终于找到解决这个问题的 ...
- QString与中文,QString与std::wstring的相互转换(使用fromStdWString和u8关键字)
Qt版本:5.5.1 Qt的QString功能丰富,对非英语语言的支持也不是问题,但支持得不够直接.例如,像 ? 1 QString str("死亡使者赛维"); 这样直接用带中文 ...
- hdu - 3572 - Task
题意:有N个作业,M台机器,每个作业1天只能同1台机器运行,每台机器1天只能运行1个作业,第i个作业需要pi天完成,且只能从Si到Ei中选Pi天,问能否完成所有作业(T <= 20, N< ...