最近项目里,写了一个通知服务,具备处理短信、电邮、站内信的能力。但我做多了一点,就是可以通过配置选择它的能力,比如只具备处理短信或者具备点油、站内信的能力。
我画了一个简单的图
图中的 Dispatcher是一个Message的中转器,它负责投递给最终的 SMS、Email、Website处理器处理。但是 Dispatcher里,我使用了硬编码来内置 SMS、Email、Website处理器(尽管我加了些判断,来区别此能力是否开启),但它的耦合太高。
所以能够如何优化呢?
观察者模式
观察者模式,有时又被称为模型(Model)-视图(View)模式、源-收听者(Listener)模式或从属者模式,是一种对象行为模式。它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
在观察者模式中,主题是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知。
这里我盗用一张图(来自)
从这张图可以知道
1、抽象主题(Subject):
它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
2、具体主题(Concrete Subject):
将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
3、抽象观察者(Observer):
为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
4、具体观察者(Concrete Observer):
实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。
所以,观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。因此稍微通知服务的那张图
具体代码实现就不贴源码了,Java也有观察者模式的实现,即Observer、Observable,前者即观察者,后者即主题,但不是接口,使用时需要继承。
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