定义
定义对象之间的一对多依赖,当一个对象状态改变时,它的所有依赖都会收到通知并且自动更新状态。
主题(Subject)是被观察的对象,而其所有依赖者(Observer)称为观察者。
类关系
主题(Subject)具有注册和移除观察者、并通知所有观察者的功能,主题是通过维护一张观察者列表来实现这些操作的。
观察者(Observer)的注册功能需要调用主题的 registerObserver() 方法。
1、创建主题定义
1 2 3 4 5 6 7 8 9
| public interface Subject {
void subscribe(EventListener eventListener); void unsubscribe(EventListener eventListener); void notifyObserver(); }
|
2、定义具体主题
创建主题的具体实现,并且构建一个容器来维护订阅关系,支持添加删除关系,以及通知订阅者。
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
| public class ConcreteSubject implements Subject{
private List<EventListener> observers = new ArrayList<>(); public void doSomething(){ System.out.println("具体主题业务逻辑实现"); notifyObserver(); }
@Override public void subscribe(EventListener eventListener) { observers.add(eventListener); }
@Override public void unsubscribe(EventListener eventListener) { observers.remove(eventListener); }
@Override public void notifyObserver() { for (EventListener eventListener : observers){ eventListener.doEvent(); } } }
|
3、定义观察者(事件监听者)
1 2 3 4
| public interface EventListener { void doEvent(); }
|
4、观察者实现
1 2 3 4 5 6
| public class EventListenerImplA implements EventListener{ @Override public void doEvent() { System.out.println("观察者 A 监听事件"); } }
|
1 2 3 4 5 6
| public class EventListenerImplB implements EventListener{ @Override public void doEvent() { System.out.println("观察者 B 监听事件"); } }
|
5、客户端测试
1 2 3 4 5 6 7 8 9
| public class Client {
public static void main(String[] args) { ConcreteSubject subject = new ConcreteSubject(); subject.subscribe(new EventListenerImplA()); subject.subscribe(new EventListenerImplB()); subject.doSomething(); } }
|
总结
一般在开发中会把主线流程开发完成后,再使用通知的方式处理辅助流程。他们可以是异步的,在MQ以及定时任务的处理下,保证最终一致性。
观察者模式达到了解耦合的效果,减少了依赖关系,每个观察者根本不需要知道发布者处理了什么业务逻辑,也不用依赖发布者任何业务模型,只关心自己本身需要处理的逻辑就可以了。
如果有新的业务添加进来,我们也只需要创建一个新的订阅者,并且维护到observers 容器中即可,也符合我们的开闭原则。
这里只是一种同步的实现方式,我们还可以扩展更多其他的异步实现方式,或者采用多线程等实现方式。
参考资料
观察者模式 (qq.com)