首先让我们来看一下定义
观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,他的所
有以来都会收到通知并自动更新。
观察者模式 = 出版者(主题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地址:
https://github.com/Stray-Kite/Design-Pattern/tree/master/src/headfirst/designpatterns/observer/weather