观察者模式 和 发布/订阅模式 之间的差异
尽管观察者模式在JavaScript世界中经常需要注意,我们会发现它通常使用称为发布/订阅模式的变体来实现。虽然非常相似,但这些模式之间的差异值得注意。
观察者模式要求希望接收主题通知的观察者(或对象)必须将该兴趣订阅给引发该事件的对象(主题)。
然而,发布/订阅模式使用位于希望接收通知的对象(发布者)和发起事件的对象(发布者)之间的主题/事件频道。这个事件系统允许代码定义特定于应用程序的事件,这些事件可以传递包含订户所需值的自定义参数这里的想法是避免用户和发布者之间的依赖关系。
这与观察者模式不同,因为它允许任何执行适当事件处理程序的订阅者注册并接收发布者广播的主题通知。
下面是一个如何在发布/订阅的情况下使用发布/订阅(如果提供的功能实现在后台为publish(),subscribe()和unsubscribe()提供支持的示例:
/* 一个简单的新邮件处理程序 */
// 收到的消息数量
var mailCounter = 0
// 初始化要监听的主题 名称为 'inbox/newMessage'
// 渲染一个预览消息
var subscriber1 = subscribe('index/newMessage', function(topic, data) {
// 记录主题以进行调试
console.log('A new message was received: ', topic)
// 使用从我们的主题传递的数据, 向用户显示消息预览
$('.messageSender').html(data.sender)
$('.messagePreview').html(data.body)
})
// 这是另一个使用相同数据执行的订户 不同的任务。
// 更新计数器显示新的数量, 通过发布者收到的消息
var subscriber2 = subscribe('index/newMessage', function(topic, data) {
$('.newMessageCounter').html(++mailCounter)
})
publish('inbox/newMessage', [{
sender: 'hello@google.com',
body: 'hey there! how are you doing today?'
}])
// 稍后我们可以退订订阅者 , 接收任何新的主题通知,如下所示:
// unsubscribe( subscriber1 );
// unsubscribe( subscriber2 );这里的一般想法是促进松耦合。而不是直接调用其他对象的方法的单个对象,而是订阅另一个对象的特定任务或活动,并在发生时通知它们。
优点
观察者和发布/订阅模式鼓励我们认真思考应用程序不同部分之间的关系。他们还帮助我们确定包含直接关系的层次,而这些关系可以用主题和观察者集合取而代之。这可以有效地将应用程序分解为更小,更松散的块,以改善代码管理和重用的潜力。
使用Observer模式的进一步动机是我们需要保持相关对象之间的一致性,而不需要使类紧密耦合。例如,当一个对象需要能够通知其他对象而不做这些对象的假设时。
使用这两种模式时,观察者和主体之间可能存在动态关系。这提供了很大的灵活性,当我们的应用程序的不同部分紧密耦合时,这可能不容易实现。
尽管对于每个问题来说,这并不总是最好的解决方案,但这些模式仍然是设计分离系统的最佳工具之一,应该被视为任何JavaScript开发人员的工具带中的重要工具。
缺点
因此,这些模式的一些问题实际上源于其主要益处。在“发布/订阅”中,通过将发布者与订阅者分离,有时可能难以获得我们应用程序的特定部分正常运行的保证。
例如,发布商可能会假定一个或多个订阅者正在倾听他们。假设我们正在使用这样的假设来记录或输出关于某些应用程序过程的错误。如果执行日志记录的用户崩溃(或出于某种原因无法运行),由于系统的解耦特性,发布者将无法看到这种情况。
这种模式的另一个缺点是用户对彼此的存在并不知情,并且对转换发布商的成本视而不见。由于用户和发布者之间的动态关系,更新依赖性很难追踪。
