设计原则:为了交互对象之间的松耦合设计而努力。
1、设计模式的一些理解
1)知道OO基础,并不足以让你设计出良好的OO系统
2)良好的OO设计必须具备可复用、可扩充、可维护三个特性
3)模式可以让我们建造出具有良好OO设计质量的系统
4)模式被认为是历经验证的OO设计经验
5)模式不是代码,而是针对设计问题的通用解决方案。你可把它们应用到特定的应用中
6)模式不是被发明,而是被发现
7)大多数的模式和原则,都着眼于软件变化的主题
8)大多数的模式都允许系统局部改变独立于其他部分
9)我们常把系统中会变化的部分抽出来封装
10)模式让开发人员之间有共享的语言,能够最大化沟通的价值
2、观察者模式:气象观测站
需求:建立一个下一代Internet气象观测站。该气象站必须建立再我们专利申请中的WeatherData对象上,由WeatherData对象负责追踪目前的天气状况(温度/湿度、气压)。我们希望贵公司能建立一个应用,有三种布告板,分别显示目前的状况、气象统计及简单的预报。当WeatherData对象获得最新的测量数据时,三种布告板必须实时更新。
而且,这是一个可以扩展的气象站,Weather-O-Rama气象站希望公布一组API,好让其他开发人员可以写出自己的气象布告板,并插入此应用中。我们希望贵公司能提供这样的API。
气象监测应用的概况:此系统中的三个部分是气象站(获取实际气象数据的物理装置)、WeatherData对象(追踪来自气象站的数据,并更新布告板)和布告板(显示目前天气状况给用户看)。WeatherData对象知道如何跟物理气象站联系,以取得更新的数据。WeatherData对象会随即更新三个布告板的显示:目前状况(温度、湿度、气压)、气象统计和天气预报。
我们的工作:建立一个应用,利用WeatherData对象取得数据,并更新三个布告板:目前状况、气象统计和天气预报。
认识观察者模式:举例报纸和杂志的订阅
1)报社的业务就是出版报纸。
2)向某家报社订阅报纸,只要他们有新报纸出版,就会给你送来。只要你是他们的订户,你就会一直收到新报纸。
3)当你不想再看报纸的时候,取消订阅,他们就不会再送新报纸来。
4)只要报社还在运营,就会一直有人向他们订阅报纸或取消订阅报纸。
出版者 + 订阅者 = 观察者模式,出版者叫做“主题”(Subject), 订阅者叫做"观察者"(Observer)。
观察者模式定义:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
观察者模式,类图设计:
Subject
public interface Subject { public void registerObserver(Observer o); public void removerObserver(Observer o); // 当主题状态改变时,这个方法会被调用,以通知所有的观察者 public void notifyObservers(); }
Observer
public interface Observer { public void update(float temp, float humidity, float pressure); }
DisplayElement
public interface DisplayElement { public void display(); }
WeatherData
public class WeatherData implements Subject { private ArrayList observers; private float temperature; private float humidity; private float pressure; public WeatherData() { observers = new ArrayList(); } @Override public void registerObserver(Observer o) { observers.add(o); } @Override public void removerObserver(Observer o) { int i = observers.indexOf(o); if (i >= 0) { observers.remove(i); } } @Override 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(); } /** * 测试时用这个方法来更新数据 * @param temperature * @param humidity * @param pressure */ public void setMeasurements(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementsChanged(); } public float getTemperature() { return temperature; } public float getHumidity() { return humidity; } public float getPressure() { return pressure; } }
CurrentConditionsDisplay
public class CurrentConditionsDisplay implements Observer, DisplayElement { private float temperature; private float humidity; private Subject weatherData; public CurrentConditionsDisplay(Subject weatherData) { this.weatherData = weatherData; weatherData.registerObserver(this); } @Override public void display() { System.out.println("Current conditions: " + temperature+ "F degrees and " + humidity + "% humidity"); } @Override public void update(float temp, float humidity, float pressure) { this.temperature = temp; this.humidity = humidity; display(); } }
测试代码:
public static void main(String[] args) { WeatherData weatherData = new WeatherData(); CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData); // 模拟新的气象测量:一旦气象数据更新就会主动"推送"给每个观察者 weatherData.setMeasurements(80, 65, 30.4f); weatherData.setMeasurements(82, 70, 29.2f); weatherData.setMeasurements(78, 90, 30.0f); // 观察者主动"拉"数据 System.out.println("观察者主动"拉"数据"); currentConditionsDisplay.update(weatherData.getTemperature(), weatherData.getHumidity(), weatherData.getPressure()); }
3、使用jdk提供的观察者相关类 java.util.Observable(主题),java.util.Observer(观察者)
WeatherData
import java.util.Observable; /** * @author oy * @date 2019年8月25日 下午8:44:06 * @version 1.0.0 */ public class WeatherData extends Observable { private float temperature; private float humidity; private float pressure; public WeatherData() {} public void measurementsChanged() { setChanged(); // 我们没有调用nodifyObservers()传送数据对象,表示我们采用的做法是"拉" notifyObservers(); } public void setMeasurements(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementsChanged(); } public float getTemperature() { return temperature; } public float getHumidity() { return humidity; } public float getPressure() { return pressure; } }
DisplayElement
public interface DisplayElement { public void display(); }
CurrentConditionsDisplay
import java.util.Observable; import java.util.Observer; /** * @author oy * @date 2019年8月25日 下午10:34:19 * @version 1.0.0 */ public class CurrentConditionsDisplay implements Observer, DisplayElement { Observable observable; private float temperature; private float humidity; public CurrentConditionsDisplay(Observable observable) { this.observable = observable; observable.addObserver(this); } @Override public void display() { System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity"); } @Override 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 static void main(String[] args) { WeatherData weatherData = new WeatherData(); weatherData.setMeasurements(80, 65, 30.4f); // 创建观察者,并注册 CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData); // 主动pull数据 currentDisplay.update(weatherData, null); // 更新数据,push数据给观察者 weatherData.setMeasurements(78, 90, 30.0f); // 当然,观察者主动pull数据 //currentDisplay.update(weatherData, null); }
注意: