参考 Head First设计模式
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
观察者模式的使用场景
比如swing中JButton可以有很多个Listener。
在数据报警中,可以给报警源注册邮件,钉钉,微信,短信等通知方式。
观察者模式类图
Java内置观察者模式的弊端
可观察者是一个“类”而不是一个“接口”,更糟的是,它甚至没有实现一个接口。这就违反了设计原则:“面向接口编程,而不是面向类编程”。不幸的是,java.util.Observable的实现有许多问题,限制了它的使用和复用。
如果你看看Observable API,你会发现setChanged()方法被保护起来了(被定义成 protected)。那又怎么样呢?这意味着:除非你继承自Observable,否则你无法创建Observable实例并组合到你自己的对象中来。这个设计违反了第二个设计原则:“多用组合,少用继承”。
观察者模式具体实现
1 2 3 4 5 6 7
| package com.hohode.model.oberver;
public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObservers(); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package com.hohode.model.oberver;
import java.util.ArrayList;
public class WeatherData implements Subject{ private ArrayList observers; private float temperature; private float humidity; private float pressure; public WeatherData() { observers = new ArrayList<>(); } public void registerObserver(Observer o) { observers.add(o); } public void removeObserver(Observer o) { int i = observers.indexOf(o); if (i >= 0) { observers.remove(i); } } 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(); }
public void setMeasurements(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementsChanged(); }
}
|
1 2 3 4 5
| package com.hohode.model.oberver;
public interface Observer { public void update(float temp,float humidity,float pressure); }
|
1 2 3 4 5
| package com.hohode.model.oberver;
public interface DisplayElement { public void display(); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package com.hohode.model.oberver;
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); } public void update(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; display(); } public void display() { System.out.println("Current conditions: " + temperature+ "F degrees and " + humidity + "% humidity");
} }
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| package com.hohode.model.oberver;
public class WeatherStation { public static void main(String[] args) { WeatherData weatherData = new WeatherData(); CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30.4f); weatherData.setMeasurements(82, 70, 29.2f); weatherData.setMeasurements(78, 90, 29.2f); } }
|