观察者模式
来源:互联网 发布:数据魔方架构 编辑:程序博客网 时间:2024/06/06 17:13
场景描述:
一个气象站应用,可以实时获取温度、湿度和气压信息,气象站提供一个封装好的类WeatherData,该类有最新的气象信息,当这些信息发生变动的时候,类中的measurementsChanged()方法会自动调用。目前气象站用到了两个布告栏,分别是目前状况和气象统计。当气象信息发生变动时,需要把最新的信息通知到着两个布告栏中。
WeatherData类图:
糟糕的实现:
为了完成这个气象站应用,我们可以用下面这种实现。
/** * 气象信息变动后,自动调用该方法 */ public void measurementsChangeed() { float temp = getTemperature(); float humidity = getHumidity(); float pressure = getPressure(); currentConditionsDisplay.update(temp, humidity, pressure); statisticsDiplay.update(temp, humidity, pressure); }
了解观察者模式:
在一些网站中,我们可以看到不少的观察者模式,比如杂志订阅,订阅了某本杂志,当这本杂志出了新刊,就会通知到所有订阅者。观察者模式有两个角色,一个是Subject,代表这本被订阅的杂志,另一个是Observer,代表订阅者。根据设计原则,针对接口编程,我们很容易想到这两个角色都要抽离出来定义成两个接口,杂志需要实现Subject,每个订阅者也要实现Observer。下面是观察者模式的类图。
观察者模式类图:
注:虚线空心三角形线代表implement ;实线箭头代表“有一个”,拥有箭头指向类的引用; 菱形实线箭头代表“有多个”;
实现:
了解了观察者模式的类图,我们现在来设计本次例子气象站的类图。其中的主题对象就是WeatherData, 观察者就是两个布告栏,布告栏除了要实现Observer接口,还需要实现一个DisplayElement接口,该接口有一个display方法,布告栏在展示的时候调用display方法。下面是气象站用观察者模式设计的类图。
有了类图,现在我们可以实现具体的代码了。代码地址:https://github.com/LiuJinan/designPatternDemo
Subject.java
/** * Created by LiuJinan on 2017/6/18. */public interface Subject { public void registerObserver(Observer observer); public void removeObserver(Observer observer); //主题变动,调用该方法通知所有观察者 public void notifyObservers();}
Observer.java
/** * Created by LiuJinan on 2017/6/18. */public interface Observer { //当气象信息变动,主题会把信息通过参数传递给观察者 public void update(float temp, float humidity, float pressure);}
DisplayElement.java
/** * Created by LiuJinan on 2017/6/18. */public interface DisplayElement { public void display();}
WeatherData.java
import java.util.ArrayList;import java.util.List;/** * Created by LiuJinan on 2017/6/18. */public class WeatherData implements Subject { private List<Observer> observers; private float temperature; private float humidity; private float pressure; public WeatherData() { observers = new ArrayList<>(); } public void measurementsChanged() { notifyObservers(); } @Override public void registerObserver(Observer observer) { observers.add(observer); } @Override public void removeObserver(Observer observer) { int i = observers.indexOf(observer); if (i >= 0) { observers.remove(observer); } } @Override public void notifyObservers() { for (Observer observer : observers) { observer.update(temperature, humidity, pressure); } } //气象站获取到最新信息,更新最新信息 public void setMeasurements(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementsChanged(); }}StatisticsDiplay.java
/** * Created by LiuJinan on 2017/6/18. */public class StatisticsDiplay implements Observer , DisplayElement { private float temperature; //温度 private float humidity; //湿度 private float pressure; //气压 private Subject weatherData; public StatisticsDiplay(Subject subject) { this.weatherData = subject; this.weatherData.registerObserver(this); } @Override public void update(float temp, float humidity, float pressure) { this.temperature = temp; this.humidity = humidity; this.pressure = pressure; display(); } @Override public void display() { //具体计算省略 String msg = "布告栏:气象统计{" + "平均温度=xx" + ", 最高温度=xx" + ", 最低温度=xx" + '}'; System.out.println(msg); }}
CurrentConditionsDisplay.java
package cn.wtzvae.observer.demo2;/** * Created by LiuJinan on 2017/6/18. */public class CurrentConditionsDisplay implements Observer, DisplayElement{ private float temperature; //温度 private float humidity; //湿度 private float pressure; //气压 private Subject weatherData; public CurrentConditionsDisplay(Subject subject) { this.weatherData = subject; this.weatherData.registerObserver(this); } @Override public void display() { String msg = "布告栏:当前状况{" + "温度=" + temperature + ", 湿度=" + humidity + ", 气压=" + pressure + '}'; System.out.println(msg); } @Override public void update(float temp, float humidity, float pressure) { this.temperature = temp; this.humidity = humidity; this.pressure = pressure; display(); }}
运行:
public static void main(String[] args) { WeatherData weatherData = new WeatherData(); CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData); StatisticsDiplay statisticsDiplay = new StatisticsDiplay(weatherData); weatherData.setMeasurements(10, 20, 30); }
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- 观察者模式
- PAT (Advanced Level) Practise 1035
- Multimodal Word Distributions
- Redis in Python: 字符串(String)
- JZOJ1266.【USACO题库】2.3.1 Longest Prefix最长前缀
- struct iovec 结构体定义与使用
- 观察者模式
- 兼容ie8 rgba()用法
- 大数据环境下该如何优雅地设计数据分层
- 3个常用基于Linux系统命令行WEB网站浏览工具(w3m/Links/Lynx)
- SpringBoot 读取配置文件属性值
- 欢迎使用CSDN-markdown编辑器
- Kinetis单片机——引脚配置
- 算法思想 -- 贪心算法(1) -- 基本概念及步骤
- 欢迎使用CSDN-markdown编辑器