WeatherData项目中观察者模式解析

一、观察者模式的实现原理

  观察者模式是软件设计模式的一种,在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。

  观察者模式通常基于Subject和Observer接口类来设计,下面是是类图

  

二、观察者模式的优缺点

优点

  1. 观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。

由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。如果被观察者和观察者都被扔到一起,那么这个对象必然跨越抽象化和具体化层次。

  2. 观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知。

缺点

  1. 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

  2. 如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。

  3. 如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。

  4. 虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。

三、观察者模式的具体实现

需求分析

  我们接到一个来自气象局的需求:气象局需要我们构建一套系统,这系统有两个公告牌,分别用于显示当前的实时天气和未来几天的天气预报。当气象局发布新的天气数据(WeatherData)后,两个公告牌上显示的天气数据必须实时更新。气象局同时要求我们保证程序拥有足够的可扩展性,因为后期随时可能要新增新的公告牌。

概况介绍
  这套系统中主要包括三个部分:气象站(获取天气数据的物理设备)、WeatherData(追踪来自气象站的数据,并更新公告牌)、公告牌(用于展示天气数据)
  WeatherData知道如何跟气象站联系,以获得天气数据。当天气数据有更新时,WeatherData会更新两个公告牌用于展示新的天气数据。
  结合观察者模式的类图,我们现在将观察者模式应用到WeatherData项目中来。于是有了下面这张类图
  
主题接口
/**
* 主题(发布者、被观察者)
*/
public interface Subject {

    /**
     * 注册观察者
     */
    void registerObserver(Observer observer); /** * 移除观察者 */ void removeObserver(Observer observer); /** * 通知观察者 */ void notifyObservers(); }
观察者借口
/**
 * 观察者
 */
public interface Observer { void update(); }

公告牌用于显示的公共接口
public interface DisplayElement { void display(); }

WeatherData实现

public class WeatherData implements Subject { private List<Observer> observers; private float temperature;//温度 private float humidity;//湿度 private float pressure;//气压 private List<Float> forecastTemperatures;//未来几天的温度 public WeatherData() { this.observers = new ArrayList<Observer>(); } @Override public void registerObserver(Observer observer) { this.observers.add(observer); } @Override public void removeObserver(Observer observer) { this.observers.remove(observer); } @Override public void notifyObservers() { for (Observer observer : observers) { observer.update(); } } public void measurementsChanged() { notifyObservers(); } public void setMeasurements(float temperature, float humidity, float pressure, List<Float> forecastTemperatures) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; this.forecastTemperatures = forecastTemperatures; measurementsChanged(); } public float getTemperature() { return temperature; } public float getHumidity() { return humidity; } public float getPressure() { return pressure; } public List<Float> getForecastTemperatures() { return forecastTemperatures; }
}

显示当前天气的公告牌CurrentConditionsDisplay

public class CurrentConditionsDisplay implements Observer, DisplayElement { private WeatherData weatherData; private float temperature;//温度 private float humidity;//湿度 private float pressure;//气压 public CurrentConditionsDisplay(WeatherData weatherData) { this.weatherData = weatherData; this.weatherData.registerObserver(this); } @Override public void display() { System.out.println("当前温度为:" + this.temperature + "℃"); System.out.println("当前湿度为:" + this.humidity); System.out.println("当前气压为:" + this.pressure); } @Override public void update() { this.temperature = this.weatherData.getTemperature(); this.humidity = this.weatherData.getHumidity(); this.pressure = this.weatherData.getPressure(); display(); } }

显示未来几天天气的公告牌ForecastDisplay

public class ForecastDisplay implements Observer, DisplayElement { private WeatherData weatherData; private List<Float> forecastTemperatures;//未来几天的温度 public ForecastDisplay(WeatherData weatherData) { this.weatherData = weatherData; this.weatherData.registerObserver(this); } @Override public void display() { System.out.println("未来几天的气温"); int count = forecastTemperatures.size(); for (int i = 0; i < count; i++) { System.out.println("第" + i + "天:" + forecastTemperatures.get(i) + "℃"); } } @Override public void update() { this.forecastTemperatures = this.weatherData.getForecastTemperatures(); display(); } }

  观察者模式将观察者和主题(被观察者)彻底解耦,主题只知道观察者实现了某一接口(也就是Observer接口)。并不需要观察者的具体类是谁、做了些什么或者其他任何细节。任何时候我们都可以增加新的观察者。因为主题唯一依赖的东西是一个实现了Observer接口的对象列表。

四、源码地址:

  https://github.com/BaronZ88/DesignPatterns/tree/master/src/com/baron/patterns/observer

  

 

转载于:https://www.cnblogs.com/ruanshuai/p/9851954.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值