《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







注意:还要考虑一个问题,update3个参数传递

1》作为update的参数直接传,最为省事,但是存在问题,不是每个Display的子类都需要完整的

    3个参数,可能是1个、2个、或者不需要,这样就造成了”浪费“

2》从上面的例子我们可以看到在WeatherData中还”隐藏“了get方法,而且Display子类中也保存WeatherData的对象,so,可以通过WeatherData.get来获取自己需要的参数也     可以不获取,但是这样,会给Display的子类带来负担


此处示情况而定
















下面给出观察者模式的定义

在对象之间设置一对多的依赖,这样一来,当对象的状态改变的时候,依赖他的多个对象就可以收到通知,并自动更新





观察者模式优点

将可观察者(Observable)和观察者解耦,WeatherData不用关心 NanjingDisplay具体是个干什么的,

准确的说WeatherData只知道自己接收了一Observer类型的,而NanjingDiaplay也只是根据自己需要,

向一个 Observable注册了

0 0
原创粉丝点击