观察者模式

系统管理员 2021-09-17 01:36 577阅读 0赞

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。

意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

如何解决:使用面向对象技术,可以将这种依赖关系弱化。

关键代码:在抽象类里有一个 ArrayList 存放观察者们。

应用实例: 1、拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。 2、西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟就是观察者,他观察菩萨洒水这个动作。

优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。

缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

使用场景:

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

注意事项: 1、JAVA 中已经有了对观察者模式的支持类。 2、避免循环引用。 3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。

实例UML图:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmdfc2h1eXU_size_16_color_FFFFFF_t_70

实例代码:

  1. /**
  2. * @author Shuyu.Wang
  3. * @package:com.shuyu.publish
  4. * @description:抽象关系者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口叫更新接口;
  5. * 抽象观察者一般用一个抽象类或者一个接口实现,更新接口通常包含一个update方法,这个方法叫更新方法。
  6. * @date 2018-11-20 23:01
  7. **/
  8. public interface Observer {
  9. void update();
  10. }
  11. /**
  12. * @author Shuyu.Wang
  13. * @package:com.shuyu.publish
  14. * @description:具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调;
  15. * @date 2018-11-20 23:19
  16. **/
  17. @Slf4j
  18. public class ConcreteObserver implements Observer {
  19. private String name;
  20. private String observerState;
  21. private ConcreteSubject concreteSubject;
  22. public ConcreteObserver(ConcreteSubject concreteSubject,String name) {
  23. this.concreteSubject=concreteSubject;
  24. this.name=name;
  25. }
  26. @Override
  27. public void update() {
  28. observerState=concreteSubject.getSubjectState();
  29. log.info("观察者的新状态是:"+name+" "+observerState);
  30. }
  31. public ConcreteSubject getConcreteSubject() {
  32. return concreteSubject;
  33. }
  34. public void setConcreteSubject(ConcreteSubject concreteSubject) {
  35. this.concreteSubject = concreteSubject;
  36. }
  37. }
  38. /**
  39. * @author Shuyu.Wang
  40. * @package:com.shuyu.publish
  41. * @description:主题或抽象通知者,一般用一个抽象类或者一个接口实现,它把所有对观察者的对象的引用
  42. * 保存在一个聚集里,每个主题都可以有任何数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象
  43. * @date 2018-11-20 22:57
  44. **/
  45. public class SubjectPub {
  46. private List<Observer> observers=new ArrayList<>();
  47. /**
  48. * @author:shuyu.wang
  49. * @description:增加观察者
  50. * @date: 2018/11/20 23:05
  51. * @param null :
  52. * @return : null
  53. */
  54. public void attach(Observer observer){
  55. observers.add(observer);
  56. }
  57. /**
  58. * @author:shuyu.wang
  59. * @description:移除观察者
  60. * @date: 2018/11/20 23:06
  61. * @param null :
  62. * @return : null
  63. */
  64. public void detach(Observer observer){
  65. observers.remove(observer);
  66. }
  67. /**
  68. * @author:shuyu.wang
  69. * @description:通知
  70. * @date: 2018/11/20 23:07
  71. * @param null :
  72. * @return : null
  73. */
  74. public void notifyA(){
  75. for (Observer o : observers) {
  76. o.update();
  77. }
  78. }
  79. }
  80. /**
  81. * @author Shuyu.Wang
  82. * @package:com.shuyu.publish
  83. * @description:具体主题或具体通知者,将有关状态存入具体观察者对象,在具体主题的内部状态改变时,
  84. * 给所有登记过的观察者发出通知
  85. * @date 2018-11-20 23:14
  86. **/
  87. @Data
  88. public class ConcreteSubject extends SubjectPub{
  89. private String subjectState;
  90. }

测试代码:

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class PublishApplicationTests {
  4. @Test
  5. public void contextLoads() {
  6. ConcreteSubject subject=new ConcreteSubject();
  7. subject.attach(new ConcreteObserver(subject,"X"));
  8. subject.attach(new ConcreteObserver(subject,"Y"));
  9. subject.attach(new ConcreteObserver(subject,"Z"));
  10. subject.setSubjectState("ABC");
  11. subject.notifyA();
  12. }
  13. }

运行结果:

2018-11-20 23:33:29.738 INFO 17908 —- [ main] com.shuyu.PublishApplicationTests : Started PublishApplicationTests in 3.895 seconds (JVM running for 5.227)
2018-11-20 23:33:29.956 INFO 17908 —- [ main] com.shuyu.publish.ConcreteObserver : 观察者的新状态是:X ABC
2018-11-20 23:33:29.956 INFO 17908 —- [ main] com.shuyu.publish.ConcreteObserver : 观察者的新状态是:Y ABC
2018-11-20 23:33:29.956 INFO 17908 —- [ main] com.shuyu.publish.ConcreteObserver : 观察者的新状态是:Z ABC

发表评论

表情:
评论列表 (有 0 条评论,577人围观)

还没有评论,来说两句吧...

相关阅读

    相关 观察模式

    package 观察者模式; / 观察者模式, 理解就是一个状态的改变, 监视他的人就会给出不同的反应和业务

    相关 观察模式

    观察者模式 Observer   观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。   这个主题对象在状态上发生变化时,会通知所有观察者对

    相关 观察模式

    什么是观察者模式 有人这么说 > 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。 > > 这个主题对象在状态上发生变化时,会通知所有观

    相关 观察模式

    场景描述:  一个气象站应用,可以实时获取温度、湿度和气压信息,气象站提供一个封装好的类WeatherData,该类有最新的气象信息,当这些信息发生变动的时候,类中的meas

    相关 观察模式

    观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。 观察者模式图: ![输入图片说明][13105107_Mf

    相关 观察模式

    什么是观察者模式? 简单的来说,观察者模式=出版者+订阅者。用比较书面的话来说的话是:定义了对象之间的一对多依赖,当一所对应的对象状态改变时,它的所有依赖者都会收到通知并

    相关 观察模式

    当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 意图:定义对象

    相关 观察模式

    对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 介绍 ...