经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
[head first 设计模式]第二章 观察者模式
来源:cnblogs  作者:alexhe101  时间:2020/12/8 9:08:32  对本文有异议

[head first 设计模式]第二章 观察者模式

假如我们有一个开发需求——建造一个气象观测站展示系统。需求方给我们提供了一个WeatherObject对象,能够自动获得最新的测量数据。而我们要建立一个应用,有三种布告版,分别显示目前的状况,气象统计,简单预报。三种布告板能即时显示WeatherObject对象中更新的数据。

?同时,我们需要这是一个可扩展的气象站,可以公布一组api,好让其他开发人员写出自己的布告板插入此应用中。

?我们首先来看看我们的大致系统框架

1.jpg

我们的工作就算建立一个应用,利用weatherData对象取得数据,并更新布告板。

根据weatherData源文件,我们的工作是实现measurementChanged(),当测量数据备妥时,measurementChanged()方法将会被调用。

2.jpg

先来看一个可能的实现,

3.jpg

很明显,这个实现并不妥当。回想第一章的OO原则,会发现我们在针对具体实现编程,这会导致当有新需求时我们必须修改程序。同时,更新布告板的代码会经常改变,我们应该尽可能将其封装。

接下来我们将应用观察者模式来改进现有设计。

以报纸订阅为例,我们像某家报社订阅报纸,只要他们有新报纸初版,就会给派送给订户。而订户不想要了,就可以取消订阅。只要报社还在运营,就不断有人订阅或者取消订阅报纸。

出版者+订阅者=观察者模式

如果了解了报纸订阅是怎么回事,观察者模式也大体如此。出版者即为观察者模式中的主题(Subject),订阅者即为观察者模式中的观察者(Observer)

4.jpg

定义观察者模式

观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖着都会收到通知并自动更新。

类图如图所示

5.jpg

观察者模式提供了一种对象设计,让主题和观察者之间松耦合。

对于观察者,主题只关心观察者实现了Observer接口,主题并不关心观察者的细节。

任何时候都可以新增观察者,因为主题唯一以来的东西是一个实现了Observer接口的对象列表,同时,也可以在任何时候删除观察者。

改变主题或观察者中的其中一方,并不会影响到另一方。

设计原则

设计应该尽可能降低交互对象之间的耦合度

依照观察者模式,得到我们的新设计

6.jpg

当前,我们暂时不用Java内置的观察者模式,而是自己实现这部分代码。

  1. public interface Observer {
  2. public void update(float temp,float humidity,float pressure);
  3. }
  1. public interface Subject {
  2. public void notifyObserver();
  3. public void removeObserver(Observer observer);
  4. public void registerObserver(Observer observer);
  5. }
  1. public interface DisplayElement {
  2. public void display();
  3. }
  1. import java.util.ArrayList;
  2. import java.util.List;
  3. public class WeatherData implements Subject {
  4. private List<Observer> Observers;
  5. private float temperature;
  6. private float humidity;
  7. private float pressure;
  8. public WeatherData()
  9. {
  10. Observers = new ArrayList<Observer>();
  11. }
  12. @Override
  13. public void notifyObserver() {
  14. for (Observer o:
  15. Observers ) {
  16. o.update(temperature,humidity,pressure);
  17. }
  18. }
  19. @Override
  20. public void removeObserver(Observer observer) {
  21. Observers.remove(observer);
  22. }
  23. @Override
  24. public void registerObserver(Observer observer) {
  25. Observers.add(observer);
  26. }
  27. public void measurementChanged()
  28. {
  29. notifyObserver();
  30. }
  31. public void setMeasurements(float temperature,float humidity,float pressure)
  32. {
  33. this.temperature = temperature;
  34. this.humidity = humidity;
  35. this.pressure = pressure;
  36. measurementChanged();
  37. }
  38. }
  1. public class CurrentConditionsDisplay implements Observer,DisplayElement{
  2. private float temperature;
  3. private float humidity;
  4. private Subject weatherData;
  5. @Override
  6. public void display() {
  7. System.out.println("Current conditions: "+temperature+"F degrees and "+humidity+"% humidity");
  8. }
  9. @Override
  10. public void update(float temp, float humidity, float pressure) {
  11. this.temperature = temp;
  12. this.humidity = humidity;
  13. display();
  14. }
  15. public CurrentConditionsDisplay( Subject weatherData) {
  16. this.weatherData = weatherData;
  17. weatherData.registerObserver(this);
  18. }
  19. }
  1. public class WeatherStation {
  2. public static void main(String[] args) {
  3. WeatherData weatherData = new WeatherData();
  4. CurrentConditionsDisplay currentConditionsDisplay =
  5. new CurrentConditionsDisplay(weatherData);
  6. weatherData.setMeasurements(80,65,30.4f);
  7. }
  8. }

使用Java内置的观察者模式

Java api有自带的观察者模式,包含Observer接口和Observable类,在使用上更加方便,很多功能已经事先准备好了。如下是我们使用Java内置观察者模式修改后的设计。

7.jpg

注册/删除观察者

调用Observable对象的addObserver方法和deleteObserver方法即可

被观察者送出通知

首先调用setChanged()方法,标记状态已经改变,后调用notifyObservers(),那么所有观察者都会调用自身的update方法。

  1. import java.util.Observable;
  2. import java.util.Observer;
  3. public class CurrentConditionsDisplay implements Observer,DisplayElement{
  4. private double temperature;
  5. private double humidity;
  6. private Observable observable;
  7. @Override
  8. public void display() {
  9. System.out.println("Current temperature "+temperature+"F degrees and "+humidity+"%humidity");
  10. }
  11. public CurrentConditionsDisplay(Observable observable)
  12. {
  13. this.observable = observable;
  14. observable.addObserver(this);
  15. }
  16. @Override
  17. public void update(Observable o, Object arg) {
  18. if(o instanceof WheatherData)
  19. {
  20. temperature = ((WheatherData) o).getTemperature();
  21. humidity = ((WheatherData) o).getHumidity();
  22. display();
  23. }
  24. }
  25. }
  1. import java.util.ArrayList;
  2. import java.util.List;
  3. import java.util.Observable;
  4. public class WheatherData extends Observable {
  5. private double temperature;
  6. private double humidity;
  7. private double pressure;
  8. public double getHumidity() {
  9. return humidity;
  10. }
  11. public double getPressure() {
  12. return pressure;
  13. }
  14. public double getTemperature()
  15. {
  16. return temperature;
  17. }
  18. public void setMeasurements(double temperature,double humidity,double pressure)
  19. {
  20. this.temperature = temperature;
  21. this.humidity = humidity;
  22. this.pressure = pressure;
  23. setChanged();
  24. notifyObservers();
  25. }
  26. }

不幸的是,observable是一个类而不是接口,导致我们难以继承其他类,同时也无法拥有自己独特的实现。

在实际使用时,我们需要权衡是使用jdk自带的观察者模式亦或是由自己实现。

原文链接:http://www.cnblogs.com/alex101/p/14027901.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号