观察者模式定义
在对象之间定义了一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象会收到通知并自动更新。
使用场景
杂志的发布订阅,微信公众号的通知等
设计原则
为了交互对象之间的松耦合设计而努力
优缺点
优点:
1、观察者和被观察者是抽象耦合的。
2、建立一套监听触发机制。
缺点:
1、如果观察者众多,通知所有的观察者会很消耗时间,这里建议异步处理。
2、可能出现循环调用。
UML类图
示例
这里应用《Head First设计模式》一书中的例子
主题(被观察者)接口
package com.study.headfirst.oberver; /** * 主题 * * @author mdl * @date 2019/12/02 */ public interface Subject { /** * 注册观察者 * * @param o */ public void registerObserver(Observer o); /** * 去除观察者 * * @param o */ public void removeObserver(Observer o); /** * 通知所有观察者 */ public void notifyObserver(); }
主题(被观察者):
package com.study.headfirst.oberver; import java.util.ArrayList; import java.util.List; /** * 被观察者 * * @author mdl * @date 2019/12/02 */ public class WeatherData implements Subject { /** *记录观察者 */ private List<Observer> os; /** *温度 */ private float temp; /** *湿度 */ private float humidity; public WeatherData() { os = new ArrayList<Observer>(); } /* (non-Javadoc) * @see com.study.headfirst.oberver.Subject#registerObserver(com.study.headfirst.oberver.Observer) */ @Override public void registerObserver(Observer o) { os.add(o); } /* (non-Javadoc) * @see com.study.headfirst.oberver.Subject#removeObserver(com.study.headfirst.oberver.Observer) */ @Override public void removeObserver(Observer o) { int i = os.indexOf(o); if (i > 0) { os.remove(i); } } /* (non-Javadoc) * @see com.study.headfirst.oberver.Subject#notifyObserver() */ @Override public void notifyObserver() { for (Observer o : os) { o.update(temp, humidity); } } public void setMeasurements(float temp, float humidity) { this.temp = temp; this.humidity = humidity; notifyObserver(); } }
观察者A(当前状态布告板):
package com.study.headfirst.oberver; /** * 当前观测布告:显示温度 * * @author mdl * @date 2019/12/02 */ public class CurrentConditionsDisplay implements DisplayElement, Observer{ private float temp; public Subject weatherData; public CurrentConditionsDisplay(Subject weatherData) { this.weatherData =weatherData; weatherData.registerObserver(this); } @Override public void display() { System.out.println("当前状况-----当前温度:" + temp); } /* (non-Javadoc) * @see com.study.headfirst.oberver.Observer#update(float) */ @Override public void update(float temp, float humidity) { // TODO Auto-generated method stub this.temp =temp; display(); } }
观察者B(天气预报布告板):
package com.study.headfirst.oberver; import com.study.headfirst.oberver.DisplayElement; import com.study.headfirst.oberver.Observer; /** * 天气预报:显示温度、湿度 * * @author mdl * @date 2019/12/09 */ public class ForcastDisplay implements DisplayElement, Observer{ private float temp; private float humidity; public Subject weatherData; public ForcastDisplay(Subject weatherData) { this.weatherData =weatherData; weatherData.registerObserver(this); } @Override public void display() { System.out.println("天气预报-----当前温度:" + temp + ", 当前湿度:" + humidity); } /* (non-Javadoc) * @see com.study.headfirst.oberver.Observer#update(float) */ @Override public void update(float temp, float humidity) { // TODO Auto-generated method stub this.temp =temp; this.humidity =humidity; display(); } }
测试:
package com.study.headfirst.oberver; /** * 观察者模式 * 1. 主题的注册、移除、通知 * 2. 观察者接受通知后的动作 * * @author mdl * @date 2019/12/02 */ public class Test { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub WeatherData subject =new WeatherData(); CurrentConditionsDisplay ccd =new CurrentConditionsDisplay(subject); ForcastDisplay forcastDisplay =new ForcastDisplay(subject); subject.setMeasurements(27f, 80f); System.out.println("=================================="); subject.setMeasurements(35f, 60f); } }