观察者模式和发布订阅模式

最近项目里,写了一个通知服务,具备处理短信、电邮、站内信的能力。但我做多了一点,就是可以通过配置选择它的能力,比如只具备处理短信或者具备点油、站内信的能力。

我画了一个简单的图

图中的 Dispatcher是一个Message的中转器,它负责投递给最终的 SMSEmailWebsite处理器处理。但是 Dispatcher里,我使用了硬编码来内置 SMSEmailWebsite处理器(尽管我加了些判断,来区别此能力是否开启),但它的耦合太高。

所以能够如何优化呢?

观察者模式

观察者模式,有时又被称为模型(Model)-视图(View)模式、源-收听者(Listener)模式或从属者模式,是一种对象行为模式。它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

在观察者模式中,主题是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知。

这里我盗用一张图(来自

从这张图可以知道

1、抽象主题(Subject):

它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。

2、具体主题(Concrete Subject):

将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。

3、抽象观察者(Observer):

为所有的具体观察者定义一个接口,在得到主题通知时更新自己。

4、具体观察者(Concrete Observer):

实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。

所以,观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。因此稍微通知服务的那张图

具体代码实现就不贴源码了,Java也有观察者模式的实现,即ObserverObservable,前者即观察者,后者即主题,但不是接口,使用时需要继承。

public class MainTest {
    public static void main(String[] args) {
        MessageObservable observable = new MessageObservable();

        Observer smsObserver = new SmsObserver(observable);
        Observer emailObserver = new EmailObserver(observable);
        Observer websiteObserver = new WebsiteObserver(observable);

        observable.accept("Message1");
    }

    public static class MessageObservable extends Observable {
        public void accept(String message) {
            setChanged();
            notifyObservers(message);
        }
    }

    public static class SmsObserver implements Observer {

        public SmsObserver(Observable observable) {
            observable.addObserver(this);
        }

        public void update(Observable o, Object arg) {
            System.out.println("SMS:" + arg);
        }
    }

    public static class EmailObserver implements Observer {

        public EmailObserver(Observable observable) {
            observable.addObserver(this);
        }

        public void update(Observable o, Object arg) {
            System.out.println("Email:" + arg);
        }
    }

    public static class WebsiteObserver implements Observer {
        public WebsiteObserver(Observable observable) {
            observable.addObserver(this);
        }

        public void update(Observable o, Object arg) {
            System.out.println("Website:" + arg);
        }
    }
}

发布订阅模式

发布订阅模式不属于基本的设计模式,在形式上和观察者模式相似,如图观察者模式实现了松耦合,而发布订阅模式是完全实现了解耦合。

从这张图可以看出,图一里的微服务也属于发布订阅模式。

这两种对比起来,观察者模式只有2个角色,主题和观察者,通常用于单个应用内;发布订阅模式则有3个角色,发布者、代理人(queue)、订阅者,通常用于跨应用,来解决应用间的耦合、消峰等;

最后想说的是,即是写代码,内功也很重要,掌握设计模式,首先能让你在写出优秀的代码,另外对于你阅读的能力也很有帮助。

原文地址:https://www.cnblogs.com/ranyabu/p/12353328.html

时间: 2024-10-18 06:37:48

观察者模式和发布订阅模式的相关文章

观察者模式 vs 发布-订阅模式

我曾经在面试中被问道,_“观察者模式和发布订阅模式的有什么区别?” _我迅速回忆起“Head First设计模式”那本书: 发布 + 订阅 = 观察者模式 “我知道了,我知道了,别想骗我” 我微笑着回答:“没有区别,它们是一样的.” 但是面试官笑了,“不,它们不一样.” 我当时的表情: 所以是我错了吗? 之后我回到家打开google查找答案.这篇文章就是我google后的总结. 在深入探讨区别之前,我们先来讨论下“观察者模式”和“发布订阅模式”. 观察者设计模式: 我认为大多数人都会同意观察者模

观察者模式和发布/订阅模式的区别

在事件总线(EventBus)的架构设计中,用到了发布/订阅模式,但发现和观察者模式挺接近,有时容易发生混淆,现试图分清一下他们的关系. 观察者模式的角色为观察者(observer)和主题(subject)对象,observer需要观察subject时,需先到subject里面进行注册(subject对象持有observer对象的集合句柄),然后,当subject对象的内部状态发生变化时,把这个变化通知所有的观察者. 发布.订阅模式的角色为发布者(publisher)和订阅者(subscribe

观察者模式与发布订阅模式的区别

观察者模式是软件设计模式的一种.在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知.这通常透过呼叫各观察者所提供的方法来实现.此种模式通常被用来实时事件处理系统. 发布/订阅模式(Pub/Sub)是一种消息模式,它有 两个参与者 :  发布者和订阅者 .发布者向 某个信道发布一条消息,订阅者绑定这个信道,当有消息发布至信道时就会 接收到一个通知.最重要的一点是, 发布者和订阅者是完全解耦的,彼此并不知晓对方 的存在.两者仅仅共享一个信道名称. 从定义上可

观察者模式和发布订阅模式(上)

观察者模式 定义:观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新. 其中有两个定义需要明确,被观察者和观察者.通常来说,这两者是一对多的,也有多对多的情景. 在网页开发中,被观察者通常是数据源,不论是内存数据,还是持久化数据,又或者是接口返回的数据,都可以作为被观察者.它一旦改变,就去改变依赖于它的节点. 观察者有很多可能,针对于网页开发,我们常常认为dom节点是观察者,一旦节点的监视的数据源发

设计模式--观察者模式(发布订阅模式)

观察者模式又叫做发布—订阅模式,是我们最常用的设计模式之一.它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知和更新. 观察者模式提供了一个订阅模型,其中对象订阅事件并在发生时得到通知,这种模式是事件驱动的编程基石,它有利益于良好的面向对象的设计. 从上面的话语我们可以得知,观察者模式主要动力是促进形成松散耦合(解耦). 设计思路: 首先先声明一个观察者对象 // 注册观察者对象 var Observer = (function (){ var Oms

观察者模式Vs发布订阅模式

1)观察者模式 观察者模式通俗的讲就是我们平事件调用(click/change等等) 大家先看这个图片.我们被观察者Subject(监听某个事件)发生改变时,观察者Observer监听到没改变做出调整.最大的特点是实现了松耦合(如何理解松耦合呢?个人认为就是当Subject 发生给变时,我们有一套对应的Observer集合,当Subject中的模块1 给变时对应的Observer1做出反应,当Subject中的模块2 给变时对应的Observer2做出反应...,不必全部都是一一对应,来实现松耦

C#设计模式--观察者模式(发布-订阅模式)

0.C#设计模式--简单工厂模式 1.C#设计模式--工厂方法模式 2.C#设计模式--抽象工厂模式 3.C#设计模式--单例模式 4.C#设计模式--建造者模式 5.C#设计模式--原型模式 6.C#设计模式--设配器模式 7.C#设计模式--装饰器模式 8.C#设计模式--代理模式 9.C#设计模式--外观模式 10.C#设计模式--桥接模式 设计模式: 观察者模式(Observer Pattern) 简单介绍: 观察者模式(Observer Pattern)是设计模式中行为模式的一种,它解

C# 委托和事件 与 观察者模式(发布-订阅模式)讲解 by天命

使用面向对象的思想 用c#控制台代码模拟猫抓老鼠 我们先来分析一下猫抓老鼠的过程 1.猫叫了 2.所有老鼠听到叫声,知道是哪只猫来了 3.老鼠们逃跑,边逃边喊:"xx猫来了,快跑啊!我是老鼠xxx" 一  双向耦合的代码 首先需要一个猫类Cat 一个老鼠类Rat 和一个测试类Program 老鼠类的代码如下 //老鼠类 public class Rat { public string Name { get; set; } //老鼠的名字 public Cat MyCat { get;

JS的发布订阅模式

JS的发布订阅模式 这里要说明一下什么是发布-订阅模式 发布-订阅模式里面包含了三个模块,发布者,订阅者和处理中心.这里处理中心相当于报刊办事大厅.发布者相当与某个杂志负责人,他来中心这注册一个的杂志,而订阅者相当于用户,我在中心订阅了这分杂志.每当发布者发布了一期杂志,办事大厅就会通知订阅者来拿新杂志.这样在结合下面的图应该很好理解了. 其实就是将发布者和订阅者解耦了,在实际开发中,经常会遇到某个方法内处理很多的逻辑,最简单的就是直接在方法内直接写.这种是高度耦合的面向过程的写法.对于代码维护