设计模式之观察者模式

一、定义:

  观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

二、观察者模式中需要如下几种角色

   1、Subject抽象主题(抽象被观察者),主要提供对观察者对象集合的增、删和通知方法。

   2、ConcreteSubject:具体主题(具体被观察者),将所有观察者放到集合里,再具体主题的内部状态发生变化时,给所有注册过的观察者发送通知。

   3、Observer:抽象观察者,是观察者的抽象类,它定义了一个更新方法,使得再得到被观察者通知时,即时更新自己。

   4、ConcrereObserver:具体观察者,实现抽象观察者的更新方法,更新自己。

三、观察者模式简单实现

1、故事情景:企业有一个人源库系统管理所有人员基本信息,还有一个是财务系统和钉钉,财务和钉钉都紧密和人员信息紧密挂钩,假设人源库是被观察者,财务和钉钉是观察者,当人员信息被修改时需要即时通知财务和钉钉更新。

2、观察者模式UML类图:

3、让我们来看看代码如何实现的

抽象观察者(Observer

  里面定义了一个更新的抽象方法

1 public interface IObserverService {
2     void update(PeopleEntity peopleEntity);
3}

具体观察者(ConcrereObserver

  不同观察者实现抽象方法

 1 /**
 2  *@author : lsy
 3  *@description: 钉钉具体观察者 
 5
*/ 6 @Service 7 public class DingDingObserverImpl implements IObserverService{ 8 @Override 9 public void update(PeopleEntity peopleEntity) { 10 System.out.println("钉钉:"+peopleEntity.toString()); 11 } 12 }
 1 /**
 2  *@author : lsy
 3  *@description: 财务具体观察者
5 */ 6 @Service 7 public class FinanceObserverImpl implements IObserverService{ 8 @Override 9 public void update(PeopleEntity peopleEntity) { 10 System.out.println("财务系统:"+peopleEntity.toString()); 11 } 12 }

抽象被观察者(Subject

  定义了新增、移除、通知观察者的抽象方法

 1 /**
 2  *@author : lsy
 3  *@description: 抽象被观察者
 4 */
 5 public interface ISubjectService {
 6     //增加观察者
 7     void attach(IObserverService observerService);
 8 
 9     //移除观察者
10     void detach(IObserverService observerService);
11 
12     //通知观察者
13     void notice(PeopleEntity peopleEntity);
14 }

具体被观察者(ConcreteSubject

  创建一个用于存放观察者List集合,并实现抽象方法

 1 /**
 2  *@author : lsy
 3  *@description: 人源库具体被观察者 5 */
 6 @Service
 7 public class PeopleBasicSubjectImpl implements ISubjectService{
 8     private List<IObserverService> observerServiceList = new ArrayList<>();
 9 
10     /**
11      * 增加观察者
12      * @param observerService
13      */
14     @Override
15     public void attach(IObserverService observerService) {
16         observerServiceList.add(observerService);
17     }
18 
19     /**
20      * 移除观察者
21      * @param observerService
22      */
23     @Override
24     public void detach(IObserverService observerService) {
25         observerServiceList.remove(observerService);
26     }
27 
28     /**
29      * 通知观察者
30      */
31     @Override
32     public void notice(PeopleEntity peopleEntity) {
33         System.out.println("人源库新增:"+peopleEntity.toString());
34         observerServiceList.forEach(observer -> observer.update(peopleEntity));
35     }
36 }

启动类:

 1 /**
 2  *@author : lsy
 3  *@description: 启动类 5 */
 6 @SpringBootApplication
 7 public class StartClass {
 8     public static void main(String[] args) {
 9         PeopleEntity peopleEntity = new PeopleEntity(1, "测试", "后端", "小菜鸟");
10         //创建两个观察者
11         IObserverService dingObserver = new DingDingObserverImpl();
12         IObserverService financeObserver = new FinanceObserverImpl();
13         //被观察者具体实现类
14         ISubjectService peopleBasicSubject = new PeopleBasicSubjectImpl();
15         //添加观察者
16         peopleBasicSubject.attach(dingObserver);
17         peopleBasicSubject.attach(financeObserver);
18         //通知观察者
19         peopleBasicSubject.notice(peopleEntity);
20 
21     }
22 }

 控制台输出:

总结 

使用观察者模式的场景:
  关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。
  事件多级触发场景。
  跨系统的消息交换场景,如消息队列、事件总线的处理机制。
优点:
  解除耦合,让耦合的双方都依赖于抽象,从而使得各自的变换都不会影响另一边的变换。

缺点:
  在应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂,而且在Java中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。

原文地址:https://www.cnblogs.com/dashuaiguo/p/10531754.html