文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2024-12-03 02:13

关注

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

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

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

1、概述

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

2、适用场景

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

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

3、实例

有以下场景:

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

发布者接口:

  1.  
  2. public interface IPublisher { 
  3.  
  4.      
  5.     void publish(IEvent event); 

订阅者接口:

  1.  
  2. public interface ISubscriber { 
  3.  
  4.      
  5.     void look(); 

事件接口:

  1.  
  2. public interface IEvent { 
  3.  
  4.      
  5.     void print(); 
  6.  

消息发送者

  1.  
  2. public class Publisher implements IPublisher{ 
  3.  
  4.     private IEvent event; 
  5.  
  6.     private List subscribers; 
  7.  
  8.     public Publisher(IEvent event, List subscribers) { 
  9.         this.event = event; 
  10.         this.subscribers = subscribers; 
  11.     } 
  12.  
  13.      
  14.     @Override 
  15.     public void publish(IEvent event){ 
  16.         event.print(); 
  17.     } 
  18.  
  19.     public IEvent getEvent() { 
  20.         return event; 
  21.     } 
  22.  
  23.     public void setEvent(IEvent event) { 
  24.         this.event = event; 
  25.     } 
  26.  
  27.     public List getSubscribers() { 
  28.         return subscribers; 
  29.     } 
  30.  
  31.     public void setSubscribers(List subscribers) { 
  32.         this.subscribers = subscribers; 
  33.     } 
  34.  

事件:

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

订阅者:

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

客户端:

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

结果:

  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)多个消费者存在的时候,可能会无法控制顺序和时间较长。 

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

 

来源:狼王编程内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯