设计模式之观察者模式-笔记

xiaoxiao2021-02-28  84

观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新 设计原则: 1、为了交互对象之间的松耦合设计而努力;松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低。 场景:气象站需要实时将测量的温度、湿度信息传回,不同的显示板,根据传回的信息更新显示对应信息,显示板依赖于气象站的信息更新,而且气象站是个可扩展的气象站,可以添加删除显示板;

气象站---->主题 显示板---->观察者 主题实时更新的信息会传给所有注册过的观察者 先建立接口: public interface Subject{ public void registerObserver(Observer o);  //用来注册观察者 public void removeObserver(Observer o);   //用来删除观察者 public void notifyObservers();    //当主题状态改变时,该方法被调用用来通知所有观察者 } public interface Observer{ public void update(float temp, float humidity, float pressure);   //所有观察者都必须实现update()方法用来更新主题传来的信息,所有需要提供该接口,使所有观察者各自实现自己的动作细节 } public interface DisplayElement{ public void display()   //显示板需要显示时,调用该方法,在各个观察者类中调用实现 } 实现气象站类: public class WeatherData implements Subject{ private ArrayList observers; //用来保存所有注册了的观察者 private float temperature; //温度 private float humidity; //湿度 private float pressure; //气压 public WeatherData(){ observers = new ArrayList(); } //将注册的观察者保存到列表中 public void registerObserver(Observer o){ observers.add(o);    } //删除观察者 public void removeObserver(Observer o){ int i = observers.indexOf(o); if(i > 0){ observers.remove(i);    } } //把状态通知到每个观察者,每个观察者都实现了update()方法 public void notifyObservers(){ for(int i = 0; i < observers.size(); i++){ Observer observer = (Observer)observers.get(i); observer.update(temperature, humidity, pressure); } } //当有更新是调用该方法通知每个观察者 public void measurementsChanged(){ notifyObservers(); } //添加用来测试的方法 public void setWeatherData(float temperature, float humidity, float pressure){ this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementsChanged(); } } 实现显示板,显示板都需要实现update()方法和display()方法 //布告板实现类 public class CurrentConditionDisplay implements Observer,DisplayElement{ private float temperature; private float humidity; private Subject weatherData; public CurrentConditionDisplay(Subject weatherData){ this.weatherData = weatherData; weatherData.registerObserver(this); } public void update(float temperature, float humidity, float pressure){ this.temperature = temperature; this.humidity = humidity; display(); } public void display(){ System.out.println("Current conditions:" + temperature +"F degrees and " + humidity + "% humidity); } } //温度信息实现类 public class StatisticsDisplay implements Observer,DisplayElement{ private float maxTemp = 0.0f; private float minTemp = 0.0f; private float tempSum = 0.0f; private int numTemperature = 0; private Subject weatherData; public StatisticsDisplay(Subject weatherData){ this.weatherData = weatherData; weatherData.registerObserver(this); } public void update(float temperature, float humidity, float pressure){ tempSum += temperature; numTemperature++; if(temperature > maxTemp){ maxTemp = temperature; } if(temperature < minTemp){ minTemp = temperature; } display(); } public void display(){ System.out.println("Avg/Max/Min temperature = " + (tempSum/numTemperature) + "/" + maxTemp + "/" + minTemp); } } public class testWeatherStation{ public static void main(String[] args){ WeatherData weatherData = new WeatherData(); CurrentConditionDisplay currentDisplay = new CurrentConditionDisplay(weatherData); StatisticsDisplay statisticDisplay = new StatisticsDisplay(); weatherData.setWeatherData(80, 69, 30.4f); weatherData.setWeatherData(76, 58, 29.7f); weatherData.setWeatherData(84, 66, 30.7f); } } //显示结果为: Current conditions:80 F degrees and 69% humidity Avg/Max/Min temperature = 80.0/80.0/80.0 Current conditions:75 F degrees and 58% humidity Avg/Max/Min temperature = 78.0/80.0/76.0 Current conditions:85 F degrees and 66% humidity Avg/Max/Min temperature = 80.0/84.0/76.0 总结:观察者模式和策略模式类似的地方是,将需要改变的函数定义成接口,每个类都调用接口函数来实现不同的动作 对于观察者模式,java API已经有内置的观察者模式,许多功能已经事先准备好了,可以比较方便使用,它的实现和上面的实现大致相同, 具体运作的不同之处在于: 1、可观察者类中实现了 setChanged() 方法,每次向观察者发送更新的消息时,要先调用 setChange() 方法,标记状态已经改变,然后调用两种 notifyObservers() 方法中的一个(notifyObservers() 和 notifyObservers(Object arg),第二种可以传送任何的数据对象给每个观察者) 2、观察者接收更新的方法和上面的不太一样,update(Observable o, Object arg) 主题本省当做第一个变量好让观察者知道是哪个主题通知它,第二个参数正式 notifyObservers() 函数传入的数据对象,如果没有说明为空 可观察者实现 setChanged() 方法的好处,是不必在每次更新后都给观察者传递更新的信息,如气象站只想在温度变化超过半度再给观察者传递更新的信息,这样就可以通过setChanged函数来控制更新的传递 使用java API内置的观察者模式的实现如下: import java.util.Observable; //可观察者(即上面实现的主题) import java.util.Observer;  //观察者 //气象站类,继承了超类Observable public class WeatherData extends Observable{ private float temperature; private float humidity; private float pressure; public WeatherData(){} public void measurementsChanged(){ setChange(); notifyObservers(); } public void setWeatherData(float temperature, float humidity, float pressure){ this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; } public float getTemperature(){ return temperature; } public float getHumidity(){ return humidity; } public float getPressure(){ return pressure; } //布告板类  import java.util.Observable; import jave.util.Observer; public class CurrentConditionDisplay implements observer,DisplayElement{ Observable observable; private float temperature; private float humidity; public CurrentConditionDisplay(Observable observable){ this.observable = observable; observable.addObserver(this); } //upate()中,要先确定观察者属于WeatherData类型,然后利用getter方法获取温度和湿度值 public void update(Observable obs, Object arg){ if(obs instanceof WeatherData){ WeatherData weatherData = (WeatherData)obs; this.temperature = weatherData.getTemperature(); this.humidity = weatherData.getHumidity(); display(); } } public void display(){ System.out.println("Current conditions:" + temperature +"F degrees and " + humidity + "% humidity); } } java API 中内置的观察者模式中可观察者 Observable 是一个类,所以必须设计一个类来继承它,如果某个类想同时具有它和另一个超类的行为,就无法实现,因为java不支持多重继承,还有就是没有Observable接口,所以无法建立自己的实现和java 内置的Observer API搭配使用,也无法将java.util 的实现换成另一套做法的实现 要点: 1、观察者模式定义了对象之间一对多的关系 2、主题用一个共同的接口来更新观察者 3、观察者和可观察者之间用一种松耦合方式结合,可观察者不知道观察者的细节,只知道观察者实现了观察者接口 4、使用此模式时,可以从被观察者处推(push)或者拉(pull)数据 5、有多个观察者时,不可以依赖特定的通知次序
转载请注明原文地址: https://www.6miu.com/read-83162.html

最新回复(0)