设计模式学习--观察者模式(Observer Pattern)
设计模式学习--观察者模式(Oberser Pattern)
什么是观察者模式?
怎么设计一个观察者模式的程序?
确定这两个对象之间的关系:
以上涉及到的设计原则:
package observerPattern;
/*** 主题接口* @author wwj**/
public interface Subject {public void registerObserver(Observer o); //这两个方法都需要一个观察者作为变量,该观察者是用那个来注册和删除的public void removeObserver(Observer o);public void notifyObserver(); //当主题状态发生改变时,这个方法会被调用,以通知所有的观察者
}
2. 定义一个观察者接口Observer
package observerPattern;
/*** 观察者接口* @author wwj**/
public interface Observer {public void update(float temp, float humidity, float pressure);
}
package observerPattern;/*** 公告板接口* @author wwj**/
public interface DisplayElement {public void display();
}
4. 定义主题类:WeatherData实现接口
package observerPattern;import java.util.ArrayList;/*** WeatherData实现了Subject接口* @author wwj**/
public class WeatherData implements Subject {private ArrayList observers; //用于记录观察者private float temperature; //温度private float humidity; //湿度private float pressure; //压力public WeatherData() {observers = new ArrayList();}@Overridepublic void registerObserver(Observer o) {observers.add(o);}@Overridepublic void removeObserver(Observer o) {int i = observers.indexOf(o);if(i >= 0) {observers.remove(i);}}@Overridepublic void notifyObserver() {for(int i = 0; i < observers.size(); i++) {Observer observer = (Observer)observers.get(i);observer.update(temperature, humidity, pressure);}}public void measurementsChanged() {notifyObserver();}public void setMeasurements(float temperature, float humidity, float pressure) {this.temperature = temperature;this.humidity = humidity;this.pressure = pressure;measurementsChanged();}}
5. 定义四个布告板类实现观察者接口和布告板接口
package observerPattern;
/*** 观察者类实现观察者接口和显示板接口* @author wwj**/
public class CurrentConditionDisplay implements Observer, DisplayElement {private float temperature;private float humidity;private Subject weathderData;public CurrentConditionDisplay(Subject weathderData) {this.weathderData = weathderData;weathderData.registerObserver(this); //注册}@Overridepublic void display() {System.out.println("Current coditions: " + temperature + "F degress and " + humidity + "% humidity");}@Overridepublic void update(float temp, float humidity, float pressure) {this.temperature = temp;this.humidity = humidity;display();}}
package observerPattern;
/*** 天气统计布告板* @author wwj**/
public class StatisticsDisplay implements Observer, DisplayElement {private float maxTemp = 0.0f;; //最大温度private float minTemp = 200; //最小温度private float tempSum = 0.0f; //统计温度和private int numReadings; //统计温度次数private WeatherData weatherData;public StatisticsDisplay(WeatherData weatherData) {this.weatherData = weatherData;weatherData.registerObserver(this);}@Overridepublic void display() {System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings) + "/" + maxTemp + "/" + minTemp);}@Overridepublic void update(float temp, float humidity, float pressure) {tempSum += temp;numReadings++;if(temp > maxTemp) {maxTemp = temp;}if(temp < minTemp) {minTemp = temp;}display();}}
package observerPattern;
/*** 天气预报布告板* @author wwj**/
public class ForecastDisplay implements Observer, DisplayElement {private float currentPressure = 29.92f; //当前气压private float lastPressure; //以往气压private WeatherData weatherData;public ForecastDisplay(WeatherData weatherData) {this.weatherData = weatherData;weatherData.registerObserver(this);}@Overridepublic void display() {System.out.println("Forcast:");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");}}@Overridepublic void update(float temp, float humidity, float pressure) {lastPressure = currentPressure;currentPressure = pressure;display();}}
package observerPattern;/*** 酷热指数布告板* * @author wwj* 注:那个计算酷热指数的公式不必深究*/
public class HeatIndexDisplay implements Observer, DisplayElement {float heatIndex = 0.0f;private WeatherData weatherData;public HeatIndexDisplay(WeatherData weatherData) {this.weatherData = weatherData;weatherData.registerObserver(this);}public void update(float t, float rh, float pressure) {heatIndex = computeHeatIndex(t, rh);display();}private float computeHeatIndex(float t, float rh) {float index = (float)((16.923 + (0.185212 * t) + (5.37941 * rh) - (0.100254 * t * rh) + (0.00941695 * (t * t)) + (0.00728898 * (rh * rh)) + (0.000345372 * (t * t * rh)) - (0.000814971 * (t * rh * rh)) +(0.0000102102 * (t * t * rh * rh)) - (0.000038646 * (t * t * t)) + (0.0000291583 * (rh * rh * rh)) + (0.00000142721 * (t * t * t * rh)) + (0.000000197483 * (t * rh * rh * rh)) - (0.0000000218429 * (t * t * t * rh * rh)) +0.000000000843296 * (t * t * rh * rh * rh)) -(0.0000000000481975 * (t * t * t * rh * rh * rh)));return index;}public void display() {System.out.println("Heat index is " + heatIndex);}
}
6. 来吧,开始测试
package observerPattern;/*** 测试类* @author wwj**/
public class WeatherStation {public static void main(String[] args) {//建立一个WeatherData对象WeatherData weatherData = new WeatherData();//第一个布告板CurrentConditionDisplay currentDisplay = new CurrentConditionDisplay(weatherData);StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);HeatIndexDisplay heatIndexDisplay = new HeatIndexDisplay(weatherData);// 模拟新的气象数据weatherData.setMeasurements(80, 65, 30.4f);weatherData.setMeasurements(82, 70, 29.2f);weatherData.setMeasurements(78, 90, 29.2f);}
}
7. 测试结果:
Current coditions: 80.0F degress and 65.0% humidity
Avg/Max/Min temperature = 80.0/80.0/80.0
Forcast:
Improving weather on the way!
Heat index is 82.95535
Current coditions: 82.0F degress and 70.0% humidity
Avg/Max/Min temperature = 81.0/82.0/80.0
Forcast:
Watch out for cooler, rainy weather
Heat index is 86.90124
Current coditions: 78.0F degress and 90.0% humidity
Avg/Max/Min temperature = 80.0/82.0/78.0
Forcast:
more of the same
Heat index is 83.64967
package weatherObservable;import java.util.Observable;
/*** 使用Java内置的观察者模式* @author wwj**/
public class WeatherData extends Observable {private float temperature;private float humidity;private float pressure;/*** 我们的构造器不再需要为了记住观察者们而建立数据结构了*/public WeatherData(){}public void measurementsChanged() {setChanged(); //Observable类方法notifyObservers();}public void setMeasurements(float temperature, float humidity, float pressure) {this.temperature = temperature;this.humidity = humidity;this.pressure = pressure;measurementsChanged();}public float getTemperature() {return temperature;}public float getHumidity() {return humidity;}public float getPressure() {return pressure;}}
2. 4个布告板中的代码稍微发生了点变化
package weatherObservable;import java.util.Observable;
import java.util.Observer;/*** 实现Java内置的观察者接口,布告板不变* @author wwj**/
public class CurrentConditionDisplay implements Observer, DisplayElement{Observable observable;private float temperature;private float humidity;public CurrentConditionDisplay(Observable observable) {this.observable = observable;observable.addObserver(this); //登记为观察者}@Overridepublic void display() {System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");}/*** 在这个方法当中,先确定可观察者属于WeatherData类型,然后利用getter方法获取温度和温度测量值,最后调用display();*/@Overridepublic void update(Observable obs, Object arg) {if(obs instanceof WeatherData) {WeatherData weatherData = (WeatherData) obs;this.temperature = weatherData.getTemperature();this.humidity = weatherData.getHumidity();display();}}}
package weatherObservable;import java.util.Observable;
import java.util.Observer;/*** 天气预报布告板* @author wwj**/
public class ForecastDisplay implements Observer, DisplayElement {private Observable observable;private float currentPressure = 29.92f; //当前气压private float lastPressure; //以往气压public ForecastDisplay(Observable observable) {this.observable = observable;observable.addObserver(this);}@Overridepublic void display() {System.out.println("Forcast:");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");}}@Overridepublic void update(Observable o, Object arg) {if (o instanceof WeatherData) {WeatherData weatherData = (WeatherData)observable;lastPressure = currentPressure;currentPressure = weatherData.getPressure();display();}}}
package weatherObservable;import java.util.Observable;
import java.util.Observer;/*** 天气统计布告板* @author wwj**/
public class StatisticsDisplay implements Observer, DisplayElement {private float maxTemp = 0.0f;; //最大温度private float minTemp = 200; //最小温度private float tempSum = 0.0f; //统计温度和private int numReadings; //统计温度次数private Observable observable;public StatisticsDisplay(Observable observable) {this.observable = observable;observable.addObserver(this);}@Overridepublic void display() {System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings) + "/" + maxTemp + "/" + minTemp);}@Overridepublic void update(Observable obs, Object arg) {if(obs instanceof WeatherData) {WeatherData weatherData = (WeatherData)obs;float temp = weatherData.getTemperature();tempSum += temp;numReadings++;if (temp > maxTemp) {maxTemp = temp;}if (temp < minTemp) {minTemp = temp;}display();}}}
package weatherObservable;import java.util.Observable;
import java.util.Observer;/*** 酷热指数布告板* * @author wwj* 注:那个计算酷热指数的公式不必深究*/
public class HeatIndexDisplay implements Observer, DisplayElement {float heatIndex = 0.0f;private WeatherData weatherData;private Observable observable;public HeatIndexDisplay(Observable observable) {this.observable = observable;observable.addObserver(this);}private float computeHeatIndex(float t, float rh) {float index = (float)((16.923 + (0.185212 * t) + (5.37941 * rh) - (0.100254 * t * rh) + (0.00941695 * (t * t)) + (0.00728898 * (rh * rh)) + (0.000345372 * (t * t * rh)) - (0.000814971 * (t * rh * rh)) +(0.0000102102 * (t * t * rh * rh)) - (0.000038646 * (t * t * t)) + (0.0000291583 * (rh * rh * rh)) + (0.00000142721 * (t * t * t * rh)) + (0.000000197483 * (t * rh * rh * rh)) - (0.0000000218429 * (t * t * t * rh * rh)) +0.000000000843296 * (t * t * rh * rh * rh)) -(0.0000000000481975 * (t * t * t * rh * rh * rh)));return index;}public void display() {System.out.println("Heat index is " + heatIndex);}@Overridepublic void update(Observable obs, Object arg) {if(obs instanceof WeatherData) {WeatherData weatherData = (WeatherData)observable;float t = weatherData.getTemperature();float rh = weatherData.getHumidity();heatIndex = computeHeatIndex(t, rh);}display();}
}
3. 测试类不变
package weatherObservable;/*** 测试类* @author wwj**/
public class WeatherStation {public static void main(String[] args) {//建立一个WeatherData对象WeatherData weatherData = new WeatherData();//第一个布告板CurrentConditionDisplay currentDisplay = new CurrentConditionDisplay(weatherData);StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);HeatIndexDisplay heatIndexDisplay = new HeatIndexDisplay(weatherData);// 模拟新的气象数据weatherData.setMeasurements(80, 65, 30.4f);weatherData.setMeasurements(82, 70, 29.2f);weatherData.setMeasurements(78, 90, 29.2f);}
}
4. 但测试结果发生了变化:观察者被通知的次序发生了变化
Heat index is 82.95535
Forcast:
Improving weather on the way!
Avg/Max/Min temperature = 80.0/80.0/80.0
Current conditions: 80.0F degrees and 65.0% humidity
Heat index is 86.90124
Forcast:
Watch out for cooler, rainy weather
Avg/Max/Min temperature = 81.0/82.0/80.0
Current conditions: 82.0F degrees and 70.0% humidity
Heat index is 83.64967
Forcast:
more of the same
Avg/Max/Min temperature = 80.0/82.0/78.0
Current conditions: 78.0F degrees and 90.0% humidity
以上的实现被认为不是那么“正确”的,为什么呢?
设计模式学习--观察者模式(Observer Pattern)相关推荐
- 锈才学设计模式之 —— 观察者模式(Observer Pattern)
锈才学设计模式之 -- 观察者模式 观察者模式:定义对象的一对多的关系,这样当主题对象改变状态时,其它的观察者对象都会收到通知,自动更新. 说明: 在真实世界中存在很多类似的模型,比如:订报纸,找中 ...
- 设计模式-观察者模式(Observer Pattern)
设计模式-观察者模式 观察者模式是使用频率最高的设计模式之一,它用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应.在观察者模式中,发生改变的对象称为观 ...
- 设计模式 - 观察者模式(Observer Pattern) Java内置 用法
观察者模式(Observer Pattern) Java内置 用法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26601659 ...
- 设计模式:观察者模式--Observer
一.什么是观察者模式 1.生活中的观察者模式 1.警察抓小偷 在现实生活中,警察抓小偷是一个典型的观察者模式「这以一个惯犯在街道逛街然后被抓为例子」,这里小偷就是被观察者,各个干警就是观察者,干警时时 ...
- 设计模式 -行为型模式_ 观察者模式Observer Pattern 之 JDK内置的实现
文章目录 概念 Code [主题] [观察者s] 观察者一 观察者二 [测试] 源码分析 java.util.Observable 目标类 java.util.Observer 观察者接口 notif ...
- 极速理解设计模式系列:2.观察者模式(Observer Pattern)
4个角色:被观察者(Subject/目标对象接口),具体被观察者(ConcreteSubject/具体目标对象),观察者(Observer),具体观察者(ConcreteObserver) ...
- 设计模式初探-观察者模式(OBSERVER)又称发布-订阅(Publish-Subscribe)依赖(Dependents)
观察者模式(OBSERVER),又称发布-订阅(Publish-Subscribe),依赖(Dependents),通过定义对象间的一对多的依赖关系,达到当一个对象的状态发生改变时,所有依赖于它的对象 ...
- Android开发中常见的设计模式深入浅出——观察者模式Observer
##最近老大写的Android项目里用到了RxBus然后我就去百度了 让我先了解RxJava 然后RxJava又是由观察者模式的变种写的 所以打算从头学一遍!!! 观察者模式 Observer 顾名思 ...
- 设计模式(行为型)之观察者模式(Observer Pattern)
PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbob ...
最新文章
- 一步一步学习hadoop(七)
- Android Studio打包~安卓打包踩坑及总结
- LeetCode 1153. 字符串转化(哈希)
- 【AI视野·今日NLP 自然语言处理论文速览 第二十八期】Wed, 1 Dec 2021
- 一起学Windows Phone7开发(十三.三 输入控件)
- ajax编写前台的时候,列表显示部分,表格显示不出来,但是可以获取到数据
- 什么是技术档案(Technical Archives)?
- python硬件测试开发工程师_硬件测试工程师
- 【CV】用于计算机视觉的 Transformer 高被引综述
- java 成绩管理系统 报告_Java学生成绩管理系统实验报告
- python操作微信电脑版_【Python】【微信】+操作电脑版微信
- VMware安装统信UOS
- python 复数的模_如何使用abs在python中返回复数?
- sql计算字段中字数的个数
- android11 前摄相头隐藏闪光灯图标
- 量化交易入门笔记-策略常用对象
- php im即时消息,im即时通讯php
- 《食物语》运营复盘 二次元女性向手游的发行之道
- FreeDOM —— 一个可迁移的网页信息抽取模型
- What?Tomcat 竟然也算中间件?
热门文章
- [C程序设计]输出所有的“水仙花数”。
- 没有权限访问网络资源/Windows7虚拟机共享文件
- 最好的防御就是进攻 任正非
- imx6q 添加intel PCIE网卡
- Nvme pcie有线千兆网卡
- pci串行端口找不到驱动程序_PCI网卡和PCIE网卡
- .NET ORM 仓储层必备的功能介绍之 FreeSql Repository 实现篇
- Attempt to invoke virtual method ‘void cn.jiguang.share.android.api.AbsPlatform.notifyError
- PXE+Kickstart无人值守安装系统
- 新颖的自我介绍_精选简单新颖的自我介绍