设计模式系列之观察者模式

开发 前端
观察者模式是一种行为设计模式, 允许你定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。

[[410142]]

本文转载自微信公众号「狼王编程」,作者狼王 。转载本文请联系狼王编程公众号。

大家好,我是狼王,一个爱打球的程序员

这篇让我们来认识一下观察者模式

1、概述

观察者模式是一种行为设计模式, 允许你定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。

2、适用场景

1)当一个对象状态的改变需要改变其他对象, 或实际对象是事先未知的或动态变化时, 可使用观察者模式。

2) 当应用中的一些对象必须观察其他对象时,可使用该模式。但仅能在有限时间内或特定情况下使用。订阅者可随时加入或离开该列表。

3、实例

有以下场景:

  1. 有一个小区,需要进行核酸检测。 
  2. 假设每个人通过关注公众号获取核酸检测结果。 

发布者接口:

  1. /** 
  2.  * 发布接口 
  3.  */ 
  4. public interface IPublisher { 
  5.  
  6.     /** 
  7.      * 发布事件 
  8.      * @param event 
  9.      */ 
  10.     void publish(IEvent event); 

订阅者接口:

  1. /** 
  2.  * 通用订阅接口 
  3.  */ 
  4. public interface ISubscriber { 
  5.  
  6.     /** 
  7.      * 查看结果 
  8.      */ 
  9.     void look(); 

事件接口:

  1. /** 
  2.  * 通用事件接口 
  3.  */ 
  4. public interface IEvent { 
  5.  
  6.     /** 
  7.      * 打印事件信息 
  8.      */ 
  9.     void print(); 
  10.  

消息发送者

  1. /** 
  2.  * 消息发送者 
  3.  */ 
  4. public class Publisher implements IPublisher{ 
  5.  
  6.     private IEvent event; 
  7.  
  8.     private List<ISubscriber> subscribers; 
  9.  
  10.     public Publisher(IEvent event, List<ISubscriber> subscribers) { 
  11.         this.event = event; 
  12.         this.subscribers = subscribers; 
  13.     } 
  14.  
  15.     /** 
  16.      * 发布消息 
  17.      * @param event 
  18.      */ 
  19.     @Override 
  20.     public void publish(IEvent event){ 
  21.         event.print(); 
  22.     } 
  23.  
  24.     public IEvent getEvent() { 
  25.         return event; 
  26.     } 
  27.  
  28.     public void setEvent(IEvent event) { 
  29.         this.event = event; 
  30.     } 
  31.  
  32.     public List<ISubscriber> getSubscribers() { 
  33.         return subscribers; 
  34.     } 
  35.  
  36.     public void setSubscribers(List<ISubscriber> subscribers) { 
  37.         this.subscribers = subscribers; 
  38.     } 
  39.  

事件:

  1. /** 
  2.  * 检测事件 
  3.  */ 
  4. public class CheckEvent implements IEvent{ 
  5.  
  6.     private String name
  7.  
  8.     private String result; 
  9.  
  10.     private ISubscriber subscriber; 
  11.  
  12.     public ISubscriber getSubscriber() { 
  13.         return subscriber; 
  14.     } 
  15.  
  16.     public void setSubscriber(ISubscriber subscriber) { 
  17.         this.subscriber = subscriber; 
  18.     } 
  19.  
  20.     public CheckEvent(String name) { 
  21.         this.name = name
  22.     } 
  23.  
  24.     @Override 
  25.     public void print() { 
  26.         subscriber.look(); 
  27.         System.out.println("事件名称:" + name); 
  28.         System.out.println("事件结果:" + result); 
  29.     } 
  30.  
  31.  
  32.     public String getName() { 
  33.         return name
  34.     } 
  35.  
  36.     public void setName(String name) { 
  37.         this.name = name
  38.     } 
  39.  
  40.     public String getResult() { 
  41.         return result; 
  42.     } 
  43.  
  44.     public void setResult(String result) { 
  45.         this.result = result; 
  46.     } 

订阅者:

  1. /** 
  2.  * 订阅者 
  3.  */ 
  4. public class User implements ISubscriber{ 
  5.  
  6.     private String name
  7.  
  8.     public User(String name) { 
  9.         this.name = name
  10.     } 
  11.  
  12.     public String getName() { 
  13.         return name
  14.     } 
  15.  
  16.     public void setName(String name) { 
  17.         this.name = name
  18.     } 
  19.  
  20.     @Override 
  21.     public void look() { 
  22.         System.out.println("检测姓名:" + name); 
  23.     } 

客户端:

  1. /** 
  2.  * 测试类 
  3.  */ 
  4. public class TestDemo { 
  5.  
  6.     public static void main(String[] args) { 
  7.         //定义两种结果 
  8.         String[] doc = {"阴性""阳性"}; 
  9.         //初始化检测事件 
  10.         CheckEvent check = new CheckEvent("核酸检测"); 
  11.         //初始化消息发布者 
  12.         Publisher publisher = new Publisher(check,new ArrayList<>()); 
  13.         //实例化接受检测的用户 
  14.         List<ISubscriber> users = new ArrayList<>(); 
  15.         for (int i = 0; i < 10; i++) { 
  16.             //初始化用户 
  17.             User user = new User("狼王" + i); 
  18.             users.add(user); 
  19.         } 
  20.         //用户订阅事件 
  21.         publisher.setSubscribers(users); 
  22.         int index
  23.         //发布检测结果 
  24.         for (int i = 0; i < 10; i++) { 
  25.             System.out.println("---------------"); 
  26.             //随机检测结果 
  27.             index = (int) (Math.random() * doc.length); 
  28.             check.setSubscriber(users.get(i)); 
  29.             check.setResult(doc[index]); 
  30.             //发布 
  31.             publisher.publish(check); 
  32.         } 
  33.  
  34.     } 

结果:

  1. --------------- 
  2. 检测姓名:狼王0 
  3. 事件名称:核酸检测 
  4. 事件结果:阴性 
  5. --------------- 
  6. 检测姓名:狼王1 
  7. 事件名称:核酸检测 
  8. 事件结果:阴性 
  9. --------------- 
  10. 检测姓名:狼王2 
  11. 事件名称:核酸检测 
  12. 事件结果:阳性 
  13. --------------- 
  14. 检测姓名:狼王3 
  15. 事件名称:核酸检测 
  16. 事件结果:阴性 
  17. --------------- 
  18. 检测姓名:狼王4 
  19. 事件名称:核酸检测 
  20. 事件结果:阳性 
  21. --------------- 
  22. 检测姓名:狼王5 
  23. 事件名称:核酸检测 
  24. 事件结果:阳性 
  25. --------------- 
  26. 检测姓名:狼王6 
  27. 事件名称:核酸检测 
  28. 事件结果:阳性 
  29. --------------- 
  30. 检测姓名:狼王7 
  31. 事件名称:核酸检测 
  32. 事件结果:阴性 
  33. --------------- 
  34. 检测姓名:狼王8 
  35. 事件名称:核酸检测 
  36. 事件结果:阴性 
  37. --------------- 
  38. 检测姓名:狼王9 
  39. 事件名称:核酸检测 
  40. 事件结果:阴性 

4、分析

代码依赖关系如下图所示:

分别定义了三个接口:事件接口,消息发布者接口,消息订阅者接口每个接口有其对应的实现。

这样设计利于后续的扩展,在不同的事件和不同的订阅者以及消息发布者,都可以进行扩展而不影响其他。

5、总结

优点:

1)开闭原则

2)业务代码解耦,具体消息订阅者和发布者没有直接关联。

缺点:

1)多个消费者存在的时候,可能会无法控制顺序和时间较长。 

好了。今天就说到这了,我还会不断分享自己的所学所想,希望我们一起走在成功的道路上!

 

责任编辑:武晓燕 来源: 狼王编程
相关推荐

2020-10-26 08:45:39

观察者模式

2013-11-26 17:09:57

Android设计模式

2022-01-29 22:12:35

前端模式观察者

2024-02-18 12:36:09

2015-11-25 11:10:45

Javascript设计观察

2021-09-06 10:04:47

观察者模式应用

2009-03-30 09:39:04

观察者思想换位设计模式

2021-01-21 05:34:14

设计模式建造者

2024-06-04 13:11:52

Python行为设计模式开发

2021-01-25 05:38:04

设计原理VueSubject

2011-04-29 09:22:22

2021-03-29 07:14:28

Spring观察者模式

2012-08-27 10:52:20

.NET架构观察者模式

2022-05-09 10:50:13

观察者模式设计模式

2020-10-20 13:33:00

建造者模式

2021-10-26 00:21:19

设计模式建造者

2020-11-05 09:38:07

中介者模式

2021-06-09 08:53:34

设计模式策略模式工厂模式

2012-01-13 15:59:07

2021-09-29 19:45:24

观察者模式Observable
点赞
收藏

51CTO技术栈公众号