观察者模式
概念其实很简单,两个主体,一个观察者,一个被观察者,当被观察者发生变化时,观察者会有相应的动作。举几个例子,和我们日常生活息息相关的红绿灯,灯就相当于被观察者,行人就相当于观察者,当灯发生变化时,行人会有相应的动作:红灯停,绿灯行,黄灯亮了等一等。再比如我们现在玩的公众号,当我们订阅了某个公众号之后,公众号每发表一篇文章,就会向订阅了它的用户发送这篇文章,我们就可以浏览这篇文章了;当我们取消订阅了,它就不会再向我们推送这篇文章了;只要这个公众号一直在运行,就会一直有人订阅它或者取消订阅。这两个主体有个统一的称呼:被观察者成为主题(Subject),观察者仍是称为观察者(Observer)。
观察者模式还有很多其他的称谓,如发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
理论上的东西讲的再多也只是停留在理论,下面我们来实现下,到底观察者模式是个什么神奇的东西。
类图
所涉及到的角色如下:
抽象主题(Subject):提供接口,可以增加和剔除观察者对象。一般用抽象类或者接口实现。
抽象观察者(Observer):提供接口,在得到主题的通知时更新自己。一般用抽象类或者接口实现。
具体主题(ConcreteSubject):将有关状态存入具体观察者,在具体主题的内部状态发生变化时,给所有注册过的观察者发出通知。一般是具体子类实现。
具体观察者(ConcreteObserver):存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用
在上述类图中,ConcreteSubject中有一个存储Observer的列表,这意味着ConcreteSubject并不需要知道引用了哪些ConcreteObserver,只要实现(继承)了Observer的对象都可以存到该列表中。在需要的时候调用Observer的update方法。
一般实现
Subject:
Observer:
ConcreteSubject:
package com.lee.myobserver.impl;
import com.lee.myobserver.Observer;
import com.lee.myobserver.Subject;
import java.util.ArrayList;
import java.util.List;
/**
* 具体主题
*/
public class ConcreteSubject implements Subject {
private List<Observer> observerList = new ArrayList<>();
private String state;
@Override
public void attach(Observer observer) {
this.observerList.add(observer);
System.out.println("向ConcreteSubject注册了一个观察者");
}
@Override
public void detach(Observer observer) {
this.observerList.remove(observer);
System.out.println("从ConcreteSubject移除了一个观察者");
}
@Override
public void notifyObservers() {
this.observerList.forEach(observer -> observer.update(this.state));
}
public void changeState(String state) {
this.state = state;
this