引入
可能有的人在面试当中被问道过,“观察者模式和发布订阅模式的有什么区别?” 其实一开始我以为这两设计模式是一样的,只是叫法有一些区别,后来随着学习的深入,才发现二者还是有区别的。
观察者模式
我认为大多数人都会同意观察者模式是学起来最好入门的,因为我们从字面意思就能知道它主要是做什么的。
这里我列举2个通俗易懂的例子:
1. 那些年,90后的小时候,我们没有手机。悠闲地上午时光,我们出门各自玩耍,临出门前会跟老妈说一下是否回家吃午饭。总在临近中午之时开始关注一个事情,“午饭好了么,是否该回家吃饭了”。没有手机可咋整?跑回去瞅瞅。老妈说,饭还没开始做呢。
于是再出去浪一会。老妈说饭马上就好了,洗手准备吃饭。于是咕咕叫的肚子变得欢喜。后来,手机成了必备品,便没了这样的烦恼。中午时分总会接到老妈的电话,语气不甚和善的喊一句:“还吃不吃饭了,麻利回来~”。
观察者模式也便是如此了。当有一到多用户(粗去玩耍的我们)都在观察一个事情(饭是否已做好)的变化。使用观察者模式(手机),不需要我们时不时的跑回家确认,事情变化发生(饭已做好)时,老妈可便捷的通知所有关注午饭的我们。
上面问题概述起来,适用观察者模式有几个要素:被观察者(老妈)、观察者(外出的我们)、事件(老妈是否做好饭)和由被观察者维护的观察者列表(老妈知道要回家吃饭的是谁)。
不知从上述实例,小伙伴是否看出隐藏的几点。
一、观察者并非一成不变。并不是每天都是所有人回家吃午饭,只有提前告知老妈要回家吃午饭的人才会接到电话。因为观察者的可变性,需要被观察者维护一个列表。
二、观察者模式可以便捷的完成目标。不需要观察者不停的轮询查看事件变化,也不需要被观察者多次询问观察者意愿。只需要观察者提前加入或离开列表,便可以由被观察者准确的进行事件通知。 说起来,微信订阅号便是观察者模式的一种实现。感兴趣的人订阅公众号,在公众号有新的文章时推送给所有订阅人。
2. 我们假设你正在找一份软件工程师的工作,对“香蕉公司”很感兴趣。所以你联系了他们的HR,给了他你的联系电话。他保证如果有任何职位空缺都会通知你。这里还有几个候选人也你一样很感兴趣。所以职位空缺大家都会知道,如果你回应了他们的通知,他们就会联系你面试。
所以,以上和“观察者模式”有什么关系呢?这里的“香蕉公司”就是Subject,用来维护Observers(和你一样的候选人),为某些event(比如职位空缺)来通知(notify)观察者。
观察者模式在软件设计中是一个对象,维护一个依赖列表,当任何状态发生改变自动通知它们。
看吧,即使是维基百科的定义,也不是很难, 对吧?
所以,如果你想在你的软件或者应用中实现观察者模式,你可以遵循上图这个流程。
发布-订阅设计模式
在观察者模式中的Subject就像一个发布者(Publisher),而观察者(Observer)完全可以看作一个订阅者(Subscriber)。subject通知观察者时,就像一个发布者通知他的订阅者。这也就是为什么很多书和文章使用“发布-订阅”概念来解释观察者设计模式。但是这里还有另外一个流行的模式叫做发布-订阅设计模式。它的概念和观察者模式非常类似。最大的区别是:
在发布-订阅模式,消息的发送方,叫做发布者(publishers),消息不会直接发送给特定的接收者(订阅者)。
意思就是发布者和订阅者不知道对方的存在。需要一个第三方组件,叫做信息中介,它将订阅者和发布者串联起来,它过滤和分配所有输入的消息。换句话说,发布-订阅模式用来处理不同系统组件的信息交流,即使这些组件不知道对方的存在。
那么如何过滤消息的呢?事实上这里有几个过程,最流行的方法是:基于主题以及基于内容。好了,就此打住,如果你感兴趣,可以去维基百科了解。
所以,我用下图表示这两个模式最重要的区别:
有感觉了吗?
我们把这些差异快速总结一下:
•在观察者模式中,观察者是知道Subject的,Subject一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有通过消息代理进行通信。•在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。•观察者模式大多数时候是同步的,比如当事件触发,Subject就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)。•观察者模式需要在单个应用程序地址空间中实现,而发布-订阅更像交叉应用模式。
尽管它们之间有区别,但有些人可能会说发布-订阅模式是观察者模式的变异,因为它们概念上是相似的。
最后我的内容如果对你有所启发,请点个关注或者在看再走,下一篇我们将会用实际代码来实现一下这两个设计模式。