观察者一般可以看做是第三者,比如在学校上自习的时候,大家肯定都有过交头接耳、各种玩耍的经历,这时总会有一个“放风”的小伙伴,当老师即将出现时及时“通知”大家老师来了。再比如,拍卖会的时候,大家相互叫价,拍卖师会观察最高标价,然后通知给其它竞价者竞价,这就是一个观察者模式。
观察者模式(Observer):定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。结构图如下: 观察者模式的主要角色如下:
抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。例子:天气观测站和气象报告板的关系。但报告板想获取观测站的数据,可以注册加入到观测站的观察者列表中,这就可以使观测站有数据更新时,自动传给气象报告板。
主题接口
package observe; /** * 主题 * */ public interface Subject { //注册观察者 public void registerObserver(Observer o); //移除观察者 public void removeObserver(Observer o); //更新观察者 public void notifyObserver(); }主题实现类:天气各类数据
package observe; import java.util.ArrayList; /** * 实现Subject */ public class WeatherData implements Subject{ private ArrayList<Observer> observers; //观察者数组 private float temp; private float humidity; private float pressure; public WeatherData() { observers = new ArrayList<Observer>(); } //增加一个观察者 public void registerObserver(Observer o) { observers.add(o); } //移除一个观察者 public void removeObserver(Observer o) { int i = observers.indexOf(o); observers.remove(i); } //通知观察者 public void notifyObserver() { for (int i = 0; i < observers.size(); i++) { Observer observer = observers.get(i); observer.update(temp,humidity,pressure); } System.out.println("更新数据~~~"); } public void measurementChanged(){ //通知观察者 notifyObserver(); } // 设置值 public void setMeasurements(float temp,float humidity,float pressure){ this.temp = temp; this.humidity = humidity; this.pressure = pressure; measurementChanged(); } }观察者接口:用于更新数据
package observe; /** * 观察者 */ public interface Observer { public void update(float temp,float humidity,float pressure); }展示接口:用于显示数据
package observe; public interface Display { //展示的接口 public void display(); }观察者实现类
package observe; /** * 基础的预测值 */ public class BasicDisplay implements Display,Observer{ private float temp; private float humidity; private float pressure; public void display() { System.out.println("BasicDisplay{" + "temp=" + temp + ", humidity=" + humidity + ", pressure=" + pressure + "}"); } public void update(float temp, float humidity, float pressure) { this.temp = temp; this.humidity = humidity; this.pressure = pressure; display(); } }测试数据
package observe; /** * 测试数据 */ public class WeatherStation { public static void main(String[] args) { WeatherData weatherData = new WeatherData(); BasicDisplay basicDisplay = new BasicDisplay(); weatherData.registerObserver(basicDisplay); weatherData.setMeasurements(1f,2f,3f); } }支付场景 在支付场景下,用户购买一件商品,当支付成功之后三方会回调自身,在这个时候系统可能会有很多需要执行的逻辑(如:更新订单状态,发送邮件通知,赠送礼品…),这些逻辑之间并没有强耦合,因此天然适合使用观察者模式去实现这些功能,当有更多的操作时,只需要添加新的观察者就能实现,完美实现了对修改关闭,对扩展开放的开闭原则。 UGC场景 在一个UGC场景下,用户发布的内容往往会经过很多流程,大部分是先发往审核系统,当审核通过之后就会出现一系列的业务逻辑,比如更新内容状态,通知给所有的粉丝等等。