23种设计模式+额外常用设计模式汇总 (持续更新)

发布-订阅模式

在软件架构中,发布订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在。同样的,订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者(如果有的话)存在。
举个报纸的例子:
还是得说一下报纸,有人说报纸不就是观察者模式,那得有多少观察者和主题?一张报纸那么多板块,订报纸的人那么多,难道要一个人一个人的通知,显然不现实。如果在记者(编辑)和读者之间加了一个载体报纸,那么这还是观察者模式吗?
无数的编辑将新闻发到报设,报社在将信息整合到报纸同意发送到读者手中,显然这不是观察者模式,观察者模式中,观察者和主题有着很强的耦合性,而在这里显然记者不认识读者,读者也不能通过报纸直接和编辑通信,这就是发布者订阅者模式,简单来说和发布者的区别就是多了一家报社。兴许我这朴实的例子并不能让你看明白,我们看一下国外的大佬怎么说?

观察者模式和发布订阅模式有什么区别?

之前我的回答是《Head First设计模式》里讲的:Publishers + Subscribers = Observer Pattern 而且GoF也说只是别称。但是众说纷纭,可能看问题的观点不同,前人是大佬,后人也要用发展性的眼观看待,我么就来看看这两种设计模式到底有什么区别。

首先我们来重新来回顾一下观察者模式:

观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。而观察者模式属于行为型模式,行为型模式关注的是对象之间的通讯,观察者模式就是观察者和被观察者之间的通讯。


由上图可以详细的看出观察者和被观察者是密切联系的。
我们再来看看发布者-订阅者模式

在“发布者-订阅者”模式中,称为发布者的消息发送者不会将消息编程为直接发送给称为订阅者的特定接收者。这意味着发布者和订阅者不知道彼此的存在。存在第三个组件,称为代理或消息代理或事件总线,它由发布者和订阅者都知道,它过滤所有传入的消息并相应地分发它们。换句话说,pub-sub是用于在不同系统组件之间传递消息的模式,而这些组件不知道关于彼此身份的任何信息。经纪人如何过滤所有消息?实际上,有几个消息过滤过程。最常用的方法有:基于主题和基于内容的。

我们放几张图,方便理解:


总结出的差异

  • 观察者模式中,观察者知道主题主题也维护观察者的记录。而在发布者/订阅者中,发布者和订阅者不需要彼此了解。他们只是在消息队列或代理的帮助下进行通信。
  • 在发布者/订阅者模式中,与观察者模式相反,组件是松散耦合的。
  • 观察者模式大多数是以同步方式实现的,即,当某个事件发生时,主题调用其所有观察者的适当方法。的发行者/订户图案在一个实施大多异步方式(使用消息队列)。
  • 观察者模式需要在单个应用程序地址空间中实现。另一方面,发布者/订阅者模式更多地是跨应用程序模式。

尽管这些模式之间存在差异,但有些人可能会说Publisher-Subscriber模式是Observer模式的变体,因为它们之间在概念上相似。而且这根本没有错。无需认真对待差异。它们是相似的,不是吗?

注: 上文参考地址:https://hackernoon.com/observer-vs-pub-sub-pattern-50d3b27f838c

优点:

  • 松耦合
    发布者与订阅者松耦合,甚至不需要知道它们的存在。由于主题才是关注的焦点,发布者和订阅者可以对系统拓扑结构保持一无所知。各自继续正常操作而无需顾及对方。
  • 可扩展性
    通过并行操作,消息缓存,基于树或基于网络的路由等技术,发布/订阅提供了比传统的客户端–服务器更好的可扩展性。

缺点:

  • 发布/订阅系统最严重的问题是其主要优点的副作用:发布者解耦订阅者。
  • 消息交付问题:发布/订阅系统必须仔细设计,才能提供特定的应用程序可能需要的更强大的系统性能,因为松耦合,无论订阅者是否正常收到发布内容,订阅器都会停止发送。
  • 订阅器中的内容随着发布者使用者的增加服务器的负载,对中介服务器是极大的考验!

UML图

具体实现

别诟病我的中文写代码,为了看的更清楚一点,因为不好理解,我看了好久的!

1.发布者接口
package 发布者订阅者模式;public interface I发布者接口<M> {public void publish(订阅器  subscribePublish, M message, boolean isInstantMsg);//使用哪个订阅器,发布什么信息
}
2.订阅者者接口
package 发布者订阅者模式;public interface I订阅者接口<M> {public void subcribe(订阅器 subscribePublish);//从哪个订阅器订阅public void unSubcribe(订阅器 subscribePublish);//取消订阅public void update(String publisher, M message);//更新操作,参考观察者模式
}
3.实际发布者1
package 发布者订阅者模式;public class Ac实际发布者<M> implements I发布者接口<M> {private String name;public Ac实际发布者(String name) {super();this.name = name;}public void publish(订阅器 subscribePublish, M message, boolean isInstantMsg) {subscribePublish.publish(this.name, message, isInstantMsg);}
}
4.实际订阅者1
 package 发布者订阅者模式;public class Ac实际订阅者<M> implements I订阅者接口<M> {public String name;public Ac实际订阅者(String name) {super();this.name = name;}public void subcribe(订阅器 subscribePublish) {subscribePublish.subcribe(this);}public void unSubcribe(订阅器 subscribePublish) {subscribePublish.unSubcribe(this);}public void update(String publisher, M message) {System.out.println(this.name + "收到" + publisher + "发来的消息:" + message.toString());}
}
5.订阅信息(报纸?RSS?微信公众号?都是)
package 发布者订阅者模式;public class 发布的信息<M> {private String publisher;private M m;public 发布的信息(String publisher, M m) {this.publisher = publisher;this.m = m;}public String getPublisher() {return publisher;}public void setPublisher(String publisher) {this.publisher = publisher;}public M getMsg() {return m;}public void setMsg(M m) {this.m = m;}
}
6.订阅器
package 发布者订阅者模式;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;public class 订阅器<M> {//订阅器名称private String name;//订阅器队列容量final int QUEUE_CAPACITY = 300; //最大订阅器数量//订阅器存储队列private BlockingQueue<发布的信息> queue = new ArrayBlockingQueue<发布的信息>(QUEUE_CAPACITY);//订阅者private List<I订阅者接口> subcribers = new ArrayList<I订阅者接口>();public 订阅器(String name) {this.name = name;}public void publish(String publisher, M message, boolean isInstantMsg) {if (isInstantMsg) {update(publisher, message);return;}发布的信息<M> m = new 发布的信息<M>(publisher, message);if (!queue.offer(m)) {update();}}public void subcribe(I订阅者接口 subcriber) {subcribers.add(subcriber);}public void unSubcribe(I订阅者接口 subcriber) {subcribers.remove(subcriber);}public void update() {发布的信息 m = null;while ((m = queue.peek()) != null) {this.update(m.getPublisher(), (M) m.getMsg());}}public void update(String publisher, M Msg) {for (I订阅者接口 subcriber : subcribers) {subcriber.update(publisher, Msg);}}
}
7.测试
package 发布者订阅者模式;public class MainTest {public static void main(String[] args) {订阅器<String> subscribePublish = new 订阅器<String>("报纸订阅平台");I发布者接口<String> publisher1 = new Ac实际发布者<String>("纽约时报");I订阅者接口<String> subcriber1 = new Ac实际订阅者<String>("特朗普");I订阅者接口<String> subcriber2 = new Ac实际订阅者<String>("普京");subcriber1.subcribe(subscribePublish);subcriber2.subcribe(subscribePublish);publisher1.publish(subscribePublish, "美国新型冠状病毒爆发的原因", true);publisher1.publish(subscribePublish, "竟然是", true);publisher1.publish(subscribePublish, "川普不作为", false);}
}

写在最后:
我叫风骨散人,名字的意思是我多想可以不低头的自由生活,可现实却不是这样。家境贫寒,总得向这个世界低头,所以我一直在奋斗,想改变我的命运给亲人好的生活,希望同样被生活绑架的你可以通过自己的努力改变现状,深知成年人的世界里没有容易二字。目前是一名在校大学生,预计考研,热爱编程,热爱技术,喜欢分享,知识无界,希望我的分享可以帮到你!
如果有什么想看的,可以私信我,如果在能力范围内,我会发布相应的博文!
感谢大家的阅读!

『设计模式』80年代的人们就已经领悟了设计模式-- 发布者/订阅者模式 (包括发布者/订阅者模式和观察者模式的区别)相关推荐

  1. 设计模式C++实现40讲(-1)什么是设计模式

    文章目录 概念 关键要素 分类 设计模式的评价指标 概念 设计模式一词最早是在建筑领域出现,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心. 建筑学的设计模式被称为建筑模 ...

  2. 『设计模式』之小试牛刀

    为了更好的学习设计模式,以及督促自己完成设计模式的学习,现提笔为记. 怎么的,每周至少也要学一个设计模式!!! 恳请大家的监督和不吝赐教,共同学习和进步! 内容主要参考自<设计模式之禅>以 ...

  3. 『设计模式』HR:不会设计模式,你好意思来面试?(面试必备设计模式)

    23种设计模式+额外常用设计模式汇总 (持续更新) 设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用.设计模式是软件开发人员在软件开发过程中面临的一 ...

  4. 『设计模式』电话接线员与中介者模式

    23种设计模式+额外常用设计模式汇总 (持续更新) 引入 在面向对象系统的设计和开发过程中,对象之间的交互和通信是最为常见的情况,因为对象间的交互本身就是一种通信. 在系统比较小的时候,可能对象间的通 ...

  5. 『设计模式』不看就亏了的设计模式总结

    23种设计模式+额外常用设计模式汇总 (持续更新) 设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用.设计模式是软件开发人员在软件开发过程中面临的一 ...

  6. 『设计模式』工厂方法模式

    23种设计模式+额外常用设计模式汇总 (持续更新) 工厂方法(Factory Method)模式 工厂方法模式是类的创建模式,其用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中. 在工 ...

  7. 『设计模式』我能进来坐坐吗?--访问者模式

    23种设计模式+额外常用设计模式汇总 (持续更新) 访问者模式 访问者( Visitor )模式的定义: 将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添 ...

  8. 『设计模式』写代码偷懒小技巧,程序开发大智慧--享元模式

    23种设计模式+额外常用设计模式汇总 (持续更新) 享元模式 享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能.这种类型的设计模式属于结构型模式,它提 ...

  9. 『数据库』朴实无华的数据库绪论

    『数据库』 朴实无华且枯燥的数据库教程–入门必看!(不收藏,真的吃亏了) 文章目录 数据库系统概述 数据模型 概念模型 数据库系统结构 数据库系统的组成 数据库系统概述 一.四个基本概念 1.数据(D ...

最新文章

  1. Jquery php 点击td变成input,修改后失去焦点发送数据
  2. 宏基因组数据提交GSA实操手册—发表文章前必备技能
  3. python(matplotlib7)——subplot 一个figure中国显示几个小图 分格显示
  4. 海拨3000点位的岛型堰塞湖
  5. 梦幻群侠传5帮派修炼_梦幻西游:2020年十大更新回顾 法连不秒空和连续战斗修复...
  6. 编写一个程序求输入字符串的长度
  7. html css字幕滚动代码,纯CSS实现滚动3D字幕
  8. mysql续型_mysql续集(查询部分)
  9. Codeforces 781B. Innokenty and a Football League
  10. usaco Ordered Fractions
  11. java 通过id获取html代码_分享代码技巧:解决 $.(“#id“).val() 获取不到空格之后的值
  12. 详细分析《三合一收款码》后台程序识别原理
  13. 计算机科学班会,计算机科学与技术学院20级13班召开“砥砺前行,“计”往开来”主题班会...
  14. 飞思卡尔系列单片机的censorship的使用
  15. 数据结构软件测试,资讯详情-java常见数据结构-柠檬班-自动化测试-软件测试培训-自学官网...
  16. 【译】浏览器如何工作:在现代web浏览器场景的之下
  17. 离散数学对学计算机有什么用
  18. wingide5-forlinux cracked
  19. 迪士尼也追踪游客数据,但它为什么没有被批判?
  20. 电商抖音直播带货SOP工作流程主播计划脚本方案

热门文章

  1. 哈工大计算机专研和学研的区别,哈工大教授发表SCI和核心期刊共26篇,发明专利6项,在交叉学科领域大放异彩!...
  2. iOS: bundle name, bundle display name, bundle identifier...
  3. calayer动画总结(一)
  4. anaconda如何更改环境配置_Anaconda环境配置2020-08-27
  5. 虚拟化技术之KVM安装与使用
  6. Android Studio经常使用配置及使用技巧(二)
  7. 福禄克中国区高管:高精度和应用性是未来测试主要发展方向
  8. I.MX6 boot from Micro SD
  9. 一个程序员的爱情故事
  10. 重新想象 Windows 8 Store Apps (59) - 锁屏