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

Posted ranyabu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了观察者模式和发布订阅模式相关的知识,希望对你有一定的参考价值。

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

我画了一个简单的图

技术图片

图中的 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)、订阅者,通常用于跨应用,来解决应用间的耦合、消峰等;

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

以上是关于观察者模式和发布订阅模式的主要内容,如果未能解决你的问题,请参考以下文章

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

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

考验手写!透析观察者模式和发布订阅模式

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

从发布-订阅模式到消息队列

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