观察者模式定义:定义了对象之间一对多的依赖,这样一来,当一个对象状态发生变化时,它所有的依赖者都会收到通知并自动更新。
个人理解:主题发生变化时,把变化情况及时通知到订阅了主题的各个观察者(订阅者)
观察者模式设计方式让主题 与 观察者 之间实现了松耦合,能够适应变化。
- 观察者模式定义了对象之间一对多的关系
- 主题使用一个共同接口来更新观察者
- 主题与观察者之间用松耦合方式结合
- 主题可以被观察者模式用push或者pull数据
- 有多个观察者时不能依赖特定的通知顺序
- Java有多种观察者模式,例如通用的java.util.Observable
- Swing大量使用观察者模式
- 此模式也被使用在JavaBeans、RMI应用中。
定义主题接口,提供主题必须实现三个方法:注册、删除、通知
public interface Subject { void registerObserver(Observer observer); void removeObserver(Observer observer); void notifyObservers(); }
实现具体的天气主题:
实现Subject接口,实现注册、删除、通知方法;
定义观察者集合用于观察者注册时使用;
定义更新天气数据setMeasurements方法,该方法内默认调用measurementsChanaged方法(调用notifyObservers,循环观察者集合,调用每个观察者的update更新方法)
public class WeatherDataSubject implements Subject{ List<Observer> observers; private float temp; private float humidity; private float pressure; public WeatherDataSubject() { observers = new ArrayList<>(); } public void registerObserver(Observer observer) { observers.add(observer); } public void removeObserver(Observer observer) { observers.remove(observer); } public void notifyObservers() { for(Observer observer:observers) { observer.update(temp, humidity , pressure); } } public void measurementsChanaged() { notifyObservers(); } public void setMeasurements(float temp, float humidity , float pressure) { this.temp = temp; this.humidity = humidity; this.pressure = pressure; measurementsChanaged(); } }
定义观察者接口:
每个观察者必须实现的update方法,用于被主题调用,实现通知功能
public interface Observer { void update(float temp,float humidity ,float pressure); }
定义观察者显示方法:
public interface DisplayElement { void display(); }
以下三个观察者实现了Observer接口、DisplayElement 显示接口:
在update方法中,默认调用display显示方法;
在具体的观察者中定义了个性化的显示方式;
public class CurrentConditionsDisplay implements Observer,DisplayElement { private float temp; private float humidity; private float pressure; @Override public void display() { System.out.println("CurrentConditionsDisplay:temp="+temp+";humidity="+humidity+";pressure="+pressure); } @Override public void update(float temp, float humidity, float pressure) { this.temp = temp; this.humidity = humidity; this.pressure = pressure; display(); } } public class StatisticsDisplay implements Observer,DisplayElement { private float temp; private float humidity; private float pressure; @Override public void display() { System.out.println("StatisticsDisplay:temp="+temp+";humidity="+humidity+";pressure="+pressure); } @Override public void update(float temp, float humidity, float pressure) { this.temp = temp; this.humidity = humidity; this.pressure = pressure; display(); } } public class ThirdPartyDisplay implements Observer,DisplayElement { private float temp; private float humidity; private float pressure; @Override public void display() { System.out.println("ThirdPartyDisplay:temp="+temp+";humidity="+humidity+";pressure="+pressure); } @Override public void update(float temp, float humidity, float pressure) { this.temp = temp; this.humidity = humidity; this.pressure = pressure; display(); } }
测试类:
public class Test { public static void main(String[] args) { //观察者 CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(); StatisticsDisplay statisticsDisplay = new StatisticsDisplay(); ThirdPartyDisplay thirdPartyDisplay = new ThirdPartyDisplay(); //主题 WeatherDataSubject subject = new WeatherDataSubject(); //把观察者注册到主题中 subject.registerObserver(currentConditionsDisplay); subject.registerObserver(statisticsDisplay); subject.registerObserver(thirdPartyDisplay); subject.setMeasurements(1,1,1); subject.setMeasurements(2,3,4); } }
输出结果:
CurrentConditionsDisplay:temp=1.0;humidity=1.0;pressure=1.0
StatisticsDisplay:temp=1.0;humidity=1.0;pressure=1.0
ThirdPartyDisplay:temp=1.0;humidity=1.0;pressure=1.0
CurrentConditionsDisplay:temp=2.0;humidity=3.0;pressure=4.0
StatisticsDisplay:temp=2.0;humidity=3.0;pressure=4.0
ThirdPartyDisplay:temp=2.0;humidity=3.0;pressure=4.0