《2》观察者模式
来源:互联网 发布:au软件录音保存 编辑:程序博客网 时间:2024/06/04 23:24
问题:
=======条件=======
一个气象站:可以用来采集温度、湿度、气压等信息
一个WheatherData类:可用来获取气象站的数据,并且提供了一些自己的方法
public class WeatherData {private int temperature;private int humidity;private int pressure;public int getHumidity() {return humidity;}public int getPressure() {return pressure;}public int getTemperature() {return temperature;}//温度、湿度、压力改变时会调用这个void parameterChanged(){}}
=======要求=======
有一个布告栏,可以实时更新气象台的数据,并且我们可以肆意的删减布告栏的类型和数量
解决方案一:
====《1》创建统一的Display布告栏接口:
public abstract class Display {abstract void update(int tem,int hum,int pre);abstract void display();}
====《2》创建布告栏子类NanjingDisplay:
public class NanjingDisplay extends Display{private int temp;private int hum;private int pre;@Overridevoid update(int tem, int hum, int pre) {this.hum = hum;this.pre = pre;this.temp = tem;display();}@Overridevoid display() {System.out.println("温度:"+temp+" 湿度: "+hum+" 气压: "+pre);}}
====《3》更新NanjingDisplay:
public class WeatherData {private int temperature;private int humidity;private int pressure;public int getHumidity() {return humidity;}public int getPressure() {return pressure;}public int getTemperature() {return temperature;}//温度、湿度、压力改变时会调用这个void parameterChanged(){int temp = getTemperature();int hum = getHumidity();int pre = getPressure();nanjingDisplay.update(temp,hum,pre);}}
这里我们不得不考虑客户的要求:多个不同种类的布告栏
1.传参:我们怎么在WheatherData中获得Display的引用
放在构造函数参数中传入,Display数量庞大的话会很麻烦
2.WheatherData的封装性考虑:
如果后续每多增加或者减少一个Diaplay类别的话,我们都得修改
parameterChanged()函数,这还只是一个onChanged函数,如果客户后续
添加别的类别的数据的changed函数,可以想像到时后的代码维护将会是非常恐
怖的工作量
方案一fail!
解决方案二:
1》changed()函数频繁修改解决方案:
根据我们之前策略模式中提到的封装变化规则,将changed()函数中的变数提取
成一个接口,很显然这个接口叫Display,而我们要调用他们的Diaplay.update()方法
2》传参数量解决方案:
这很简单创建一个Dispaly[]数组即可,我们可以借助数组进行增加和删减操作
以上这些解决方案就接近我们的观察者模式了
3》现在让我们加入对接口编程这个规则,把对Display数组的增删操作封装成一个接口,
Observable,这个就是被监听者了,将所有的希望接受气象数据的Display抽象成Observer接口
4》在加入多用组合少用继承的规则,在Observable中用Display[]数组将 Observer们组合到自己旗下;
所谓组合,即形容此时在Display[]数组中这些 Observer对象之间的关系,他们不是通过继承来达到的,而是组合
下面引入观察者模式框架图
下面引入代码
三个接口:
public interface Observable {boolean registerObserver(Observer o);boolean unregisterObserver(Observer o);void notifyObservers();}
public interface Observer {void update(int arg0,int arg1,int arg2);}
public abstract class Display {abstract void display();}
Display子类:
public class NanjingDisplay extends Display implements Observer{private int temp;private int hum;private int pre;private Observable observable;public NanjingDisplay(Observable observable) {//这里认为要不要监听气象数据应该是各个Display自己应该//思考的事,故而将这个注册行为写在NanjingDisplay类内observable.registerObserver(this);//这里需要保留observable的引用,方便unregisterthis.observable = observable;}@Overridepublic void update(int tem, int hum, int pre) {this.hum = hum;this.pre = pre;this.temp = tem;display();}@Overridevoid display() {System.out.println("南京气象更新=="+"温度:"+temp+" 湿度: "+hum+" 气压: "+pre);}}
WheatherData类:
public class WeatherData implements Observable{private int temperature;private int humidity;private int pressure;public int getHumidity() {return humidity;}public int getPressure() {return pressure;}public int getTemperature() {return temperature;}//温度、湿度、压力改变时会调用这个void parameterChanged(int arg0,int arg1,int arg2){temperature = arg0;humidity = arg1;pressure = arg2;notifyObservers();}ArrayList<Observer> observers = new ArrayList<>();@Overridepublic boolean registerObserver(Observer o) {if (o ==null){return false;}observers.add(o);return true;}@Overridepublic boolean unregisterObserver(Observer o) {int i = observers.indexOf(o);if (i < 0){return false;}else{observers.remove(i);return true;}}@Overridepublic void notifyObservers() {if (observers.size() == 0){return;}for(Observer o: observers){o.update(temperature, humidity, pressure);}}}
Test测试类:
public class Test {public static void main(String[] args) {WeatherData observable = new WeatherData();Display nanjingDisplay = new NanjingDisplay(observable);Display beijingDisplay = new BeijingDisplay(observable);observable.parameterChanged(1,2,3);observable.parameterChanged(4,5,6);observable.parameterChanged(7,8,9);}}
测试结果:
南京气象更新==温度:1湿度:2气压:3
北京气象更新==温度:1湿度:2气压:3
南京气象更新==温度:4湿度:5气压:6
北京气象更新==温度:4湿度:5气压:6
南京气象更新==温度:7湿度:8气压:9
北京气象更新==温度:7湿度:8气压:9
注意:还要考虑一个问题,update的3个参数传递
1》作为update的参数直接传,最为省事,但是存在问题,不是每个Display的子类都需要完整的
3个参数,可能是1个、2个、或者不需要,这样就造成了”浪费“
2》从上面的例子我们可以看到在WeatherData中还”隐藏“了get方法,而且Display子类中也保存了WeatherData的对象,so,可以通过WeatherData.get来获取自己需要的参数也 可以不获取,但是这样,会给Display的子类带来负担
此处示情况而定
下面给出观察者模式的定义
在对象之间设置一对多的依赖,这样一来,当对象的状态改变的时候,依赖他的多个对象就可以收到通知,并自动更新
观察者模式优点
将可观察者(Observable)和观察者解耦,WeatherData不用关心 NanjingDisplay具体是个干什么的,
准确的说WeatherData只知道自己接收了一个Observer类型的,而NanjingDiaplay也只是根据自己需要,
向一个 Observable注册了
- Headfirst-2 观察者模式
- 观察者模式 - 2
- 观察者模式2
- 2、观察者模式
- js观察者模式2
- 《2》观察者模式
- 设计模式2 观察者模式
- 设计模式(2)--观察者模式
- 设计模式-2-观察者模式
- 设计模式-观察者模式2
- 观察者模式实现2--事件
- 设计模式之观察者2
- java中的观察者模式2
- 第二章 观察者模式2
- 设计模式-2-观察者模式(2)
- Java与设计模式(2)--观察者模式
- JAVA设计模式之观察者模式2
- Head First 设计模式2 观察者模式
- IOS改变导航栏标题颜色
- 百度前端笔试题及答案
- python 编码注释问题
- struts2的#$%区别!
- JPA EntityManager详解
- 《2》观察者模式
- iconv用法解读
- perl 微信 获取消息
- Java Code Examples for org.apache.commons.codec.binary.Base64InputStream
- java学习之路
- android Universal-Image-Loader oom:关于bitmap的优化及其他优化
- 大数据量时Mysql的优化要点
- js 方法的动态调用 apply的用法
- iOS [[UIDevice currentDevice] systemName]的返回值