设计模式之观察者模式
首先让我们来看一下定义
观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,他的所
有以来都会收到通知并自动更新。
观察者模式 = 出版者(主题Subject)+ 订阅者(观察者Observer)
现在来看一个通俗易懂的图,进而对观察者模式有进一步了解:
然后让我们利用观察这模式来做一个简单的气象监测应用:
项目概况了解:此系统中的三个部分分别是气象站(获取市级气象数据的物理装置),WeatherData对象(追中来自
气象站的数据,并更新布告板)和布告板(显示目前天气状况给用户看)。
WeatherData对象知道如何跟物理气象站联系,以获得更新的数据。WeatherData对象会随机更新三个布告板的显
示;目前状况(温度、湿度、气压)、气象统计和天气预报。
接下来看一下这个系统的设计图(运用观察者模式):
我们实现ForecastDisplay显示器,其他两个不用管,都和ForecastDisplay大同小异。
项目的实施:
首先是我们的三个接口:
Subject.java:
1 public interface Subject { 2 public void registerObserver(Observer o);//注册观察者 3 public void removeObserver(Observer o); //删除观察者 4 public void notifyObservers(); //提示更新 5 }
Observer.java:
1 public interface Observer { 2 public void update(float temp, float humidity, float pressure); //更新数据 3 }
DisplayElement.java:
1 public interface DisplayElement { 2 public void display(); 3 }
Weather.java(实现主题):
1 import java.util.ArrayList; 2 3 public class WeatherData implements Subject{ 4 private ArrayList<Observer> observers; 5 private float temperature; //温度 6 private float humidity; //湿度 7 private float pressure; //气压 8 9 public WeatherData(){ 10 observers = new ArrayList<Observer>(); 11 } 12 13 //注册观察者 14 public void registerObserver(Observer o){ 15 observers.add(o); 16 } 17 18 //删除观察者 19 public void removeObserver(Observer o){ 20 int i = observers.indexOf(o); 21 if(i >= 0){ 22 observers.remove(i); 23 } 24 } 25 26 //获取数据,从而更新 27 public void notifyObservers(){ 28 for (Observer observer: observers){ 29 observer.update(temperature, humidity, pressure); 30 } 31 } 32 33 //监测数据变化,从而触发数据更新 34 public void measurementsChanged() { 35 notifyObservers(); 36 } 37 38 //设置更新数据 39 public void setMeasurements(float temperature, float humidity, float pressure) { 40 this.temperature = temperature; 41 this.humidity = humidity; 42 this.pressure = pressure; 43 measurementsChanged(); 44 } 45 46 //下面是三个getter,分别是获取温度、湿度、气压 47 public float getTemperature() { 48 return temperature; 49 } 50 51 public float getHumidity() { 52 return humidity; 53 } 54 55 public float getPressure() { 56 return pressure; 57 } 58 }
开始建立布告板:
CurrentCOnditionsDisplay.java:
1 //实现Observer和DisplayElement连个接口,说白了就是实现update和display两个方法 2 public class CurrentConditionsDisplay implements Observer,DisplayElement{ 3 private float temperature; 4 private float humidity; 5 private Subject weatherData; 6 7 public CurrentConditionsDisplay(Subject weatherData) { 8 this.weatherData = weatherData; 9 weatherData.registerObserver(this); 10 } 11 12 public void update(float temperature, float humidity, float pressure) { 13 this.temperature = temperature; 14 this.humidity = humidity; 15 display(); 16 } 17 18 public void display() { 19 System.out.println("Current conditions: " + temperature 20 + "F degrees and " + humidity + "% humidity"); 21 } 22 }
最后让我们添加一个测试类:
Main.java:
1 public class Main { 2 3 public static void main(String[] args) { 4 WeatherData weatherData = new WeatherData(); 5 CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData); 6 // StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData); //这两个布告板都是大同小异 7 // ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData); //有兴趣的读者可以去我的GitHub上面下载 8 9 weatherData.setMeasurements(80, 65, 30.4f); 10 weatherData.setMeasurements(82, 70, 29.2f); 11 weatherData.setMeasurements(78, 90, 29.2f); 12 } 13 }
测试结果:
此项目的GitHub地址: