观察者模式

叁歲伎倆 2022-06-14 10:24 255阅读 0赞

场景描述:

一个气象站应用,可以实时获取温度、湿度和气压信息,气象站提供一个封装好的类WeatherData,该类有最新的气象信息,当这些信息发生变动的时候,类中的measurementsChanged()方法会自动调用。目前气象站用到了两个布告栏,分别是目前状况和气象统计。当气象信息发生变动时,需要把最新的信息通知到着两个布告栏中。

Center

WeatherData类图:

Center 1

糟糕的实现:

为了完成这个气象站应用,我们可以用下面这种实现。

  1. /**
  2. * 气象信息变动后,自动调用该方法
  3. */
  4. public void measurementsChangeed() {
  5. float temp = getTemperature();
  6. float humidity = getHumidity();
  7. float pressure = getPressure();
  8. currentConditionsDisplay.update(temp, humidity, pressure);
  9. statisticsDiplay.update(temp, humidity, pressure);
  10. }

其中currentConditionsDisplay和statisticsDiplay代表两个布告栏。目前这两个类都具有temperature、humidity、pressure属性和update、display方法。根据上面的实现,当气象信息变动的时候,这两个布告栏也能实时变动。但是当要增加其他布告栏的时候WeatherData对象也要变动,而且两个布告栏没有实现一个相同的接口,违反了设计原则中的针对接口编程,无法在运行时删除或者增加布告栏。为了更好的实现,需要封装程序中改变的部分,下次增加其他布告栏时只需要修改到要改变的部分,如今WeatherData和布告栏的实现是耦合在一起。

了解观察者模式:
在一些网站中,我们可以看到不少的观察者模式,比如杂志订阅,订阅了某本杂志,当这本杂志出了新刊,就会通知到所有订阅者。观察者模式有两个角色,一个是Subject,代表这本被订阅的杂志,另一个是Observer,代表订阅者。根据设计原则,针对接口编程,我们很容易想到这两个角色都要抽离出来定义成两个接口,杂志需要实现Subject,每个订阅者也要实现Observer。下面是观察者模式的类图。

观察者模式类图:

注:虚线空心三角形线代表implement ;实线箭头代表“有一个”,拥有箭头指向类的引用; 菱形实线箭头代表“有多个”;

Center 2

实现:

了解了观察者模式的类图,我们现在来设计本次例子气象站的类图。其中的主题对象就是WeatherData, 观察者就是两个布告栏,布告栏除了要实现Observer接口,还需要实现一个DisplayElement接口,该接口有一个display方法,布告栏在展示的时候调用display方法。下面是气象站用观察者模式设计的类图。

Center 3

有了类图,现在我们可以实现具体的代码了。代码地址:https://github.com/LiuJinan/designPatternDemo

Subject.java

  1. /**
  2. * Created by LiuJinan on 2017/6/18.
  3. */
  4. public interface Subject {
  5. public void registerObserver(Observer observer);
  6. public void removeObserver(Observer observer);
  7. //主题变动,调用该方法通知所有观察者
  8. public void notifyObservers();
  9. }

Observer.java

  1. /**
  2. * Created by LiuJinan on 2017/6/18.
  3. */
  4. public interface Observer {
  5. //当气象信息变动,主题会把信息通过参数传递给观察者
  6. public void update(float temp, float humidity, float pressure);
  7. }

DisplayElement.java

  1. /**
  2. * Created by LiuJinan on 2017/6/18.
  3. */
  4. public interface DisplayElement {
  5. public void display();
  6. }

WeatherData.java

  1. import java.util.ArrayList;
  2. import java.util.List;
  3. /**
  4. * Created by LiuJinan on 2017/6/18.
  5. */
  6. public class WeatherData implements Subject {
  7. private List<Observer> observers;
  8. private float temperature;
  9. private float humidity;
  10. private float pressure;
  11. public WeatherData() {
  12. observers = new ArrayList<>();
  13. }
  14. public void measurementsChanged() {
  15. notifyObservers();
  16. }
  17. @Override
  18. public void registerObserver(Observer observer) {
  19. observers.add(observer);
  20. }
  21. @Override
  22. public void removeObserver(Observer observer) {
  23. int i = observers.indexOf(observer);
  24. if (i >= 0) {
  25. observers.remove(observer);
  26. }
  27. }
  28. @Override
  29. public void notifyObservers() {
  30. for (Observer observer : observers) {
  31. observer.update(temperature, humidity, pressure);
  32. }
  33. }
  34. //气象站获取到最新信息,更新最新信息
  35. public void setMeasurements(float temperature, float humidity, float pressure) {
  36. this.temperature = temperature;
  37. this.humidity = humidity;
  38. this.pressure = pressure;
  39. measurementsChanged();
  40. }
  41. }

StatisticsDiplay.java

  1. /**
  2. * Created by LiuJinan on 2017/6/18.
  3. */
  4. public class StatisticsDiplay implements Observer , DisplayElement {
  5. private float temperature; //温度
  6. private float humidity; //湿度
  7. private float pressure; //气压
  8. private Subject weatherData;
  9. public StatisticsDiplay(Subject subject) {
  10. this.weatherData = subject;
  11. this.weatherData.registerObserver(this);
  12. }
  13. @Override
  14. public void update(float temp, float humidity, float pressure) {
  15. this.temperature = temp;
  16. this.humidity = humidity;
  17. this.pressure = pressure;
  18. display();
  19. }
  20. @Override
  21. public void display() {
  22. //具体计算省略
  23. String msg = "布告栏:气象统计{" +
  24. "平均温度=xx" +
  25. ", 最高温度=xx" +
  26. ", 最低温度=xx" +
  27. '}';
  28. System.out.println(msg);
  29. }
  30. }

CurrentConditionsDisplay.java

  1. package cn.wtzvae.observer.demo2;
  2. /**
  3. * Created by LiuJinan on 2017/6/18.
  4. */
  5. public class CurrentConditionsDisplay implements Observer, DisplayElement{
  6. private float temperature; //温度
  7. private float humidity; //湿度
  8. private float pressure; //气压
  9. private Subject weatherData;
  10. public CurrentConditionsDisplay(Subject subject) {
  11. this.weatherData = subject;
  12. this.weatherData.registerObserver(this);
  13. }
  14. @Override
  15. public void display() {
  16. String msg = "布告栏:当前状况{" +
  17. "温度=" + temperature +
  18. ", 湿度=" + humidity +
  19. ", 气压=" + pressure +
  20. '}';
  21. System.out.println(msg);
  22. }
  23. @Override
  24. public void update(float temp, float humidity, float pressure) {
  25. this.temperature = temp;
  26. this.humidity = humidity;
  27. this.pressure = pressure;
  28. display();
  29. }
  30. }

运行:

  1. public static void main(String[] args) {
  2. WeatherData weatherData = new WeatherData();
  3. CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);
  4. StatisticsDiplay statisticsDiplay = new StatisticsDiplay(weatherData);
  5. weatherData.setMeasurements(10, 20, 30);
  6. }

Center 4

发表评论

表情:
评论列表 (有 0 条评论,255人围观)

还没有评论,来说两句吧...

相关阅读

    相关 观察模式

    package 观察者模式; / 观察者模式, 理解就是一个状态的改变, 监视他的人就会给出不同的反应和业务

    相关 观察模式

    观察者模式 Observer   观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。   这个主题对象在状态上发生变化时,会通知所有观察者对

    相关 观察模式

    什么是观察者模式 有人这么说 > 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。 > > 这个主题对象在状态上发生变化时,会通知所有观

    相关 观察模式

    场景描述:  一个气象站应用,可以实时获取温度、湿度和气压信息,气象站提供一个封装好的类WeatherData,该类有最新的气象信息,当这些信息发生变动的时候,类中的meas

    相关 观察模式

    观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。 观察者模式图: ![输入图片说明][13105107_Mf

    相关 观察模式

    什么是观察者模式? 简单的来说,观察者模式=出版者+订阅者。用比较书面的话来说的话是:定义了对象之间的一对多依赖,当一所对应的对象状态改变时,它的所有依赖者都会收到通知并

    相关 观察模式

    当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 意图:定义对象

    相关 观察模式

    对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 介绍 ...