设计模式之美-行为型-观察者模式

Posted 斌哥Java工作学习笔记

tags:

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

https://time.geekbang.org    极客时间-设计模式之美-笔记


原理及应用场景剖析
观察者模式(Observer Design Pattern)也被称为发布订阅模式,在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。
被依赖的对象叫做被观察者(Observable),依赖的对象叫作观察者(Observer)
观察者模式是一个比较抽象的模式,根据不同的场景和需求,又完全不同的实现方式。
public interface Subject { void registerObserver(Observer observer); void removeObserver(Observer observer); void notifyObservers(Message message);}
public interface Observer { void update(Message message);}
public class ConcreteSubject implements Subject { private List<Observer> observers = new ArrayList<Observer>();
@Override public void registerObserver(Observer observer) { observers.add(observer); }
@Override public void removeObserver(Observer observer) { observers.remove(observer); }
@Override public void notifyObservers(Message message) { for (Observer observer : observers) { observer.update(message); } }
}
public class ConcreteObserverOne implements Observer { @Override public void update(Message message) { //TODO: 获取消息通知,执行自己的逻辑... System.out.println("ConcreteObserverOne is notified."); }}
public class ConcreteObserverTwo implements Observer { @Override public void update(Message message) { //TODO: 获取消息通知,执行自己的逻辑... System.out.println("ConcreteObserverTwo is notified."); }}
public class Demo { public static void main(String[] args) { ConcreteSubject subject = new ConcreteSubject(); subject.registerObserver(new ConcreteObserverOne()); subject.registerObserver(new ConcreteObserverTwo()); subject.notifyObservers(new Message()); }}
上面的代码算是观察者哦是的“模版代码”, 只能反应大体的设计思路。观察者模式的实现方法各式各样,函数、类的命名等会根据业务场景的不同有很大的差别。
假设在一个p2p投资理财系统,用户注册成功之后,我们会发放投资体验金。代码大致是下面的样子;
public class UserController { private UserService userService; // 依赖注入 private PromotionService promotionService; // 依赖注入
public Long register(String telephone, String password) { //省略输入参数的校验代码 //省略userService.register()异常的try-catch代码 long userId = userService.register(telephone, password); promotionService.issueNewUserExperienceCash(userId); return userId; }}
虽然注册接口做了两件事,注册和发放体验金,违反单一职责原则,但是如果没有扩展和修改的需求,现在的代码实现是可以接受的。
但是如果需求频繁变动,如,注册成功后,不再发放体验金,而是优惠卷,并且嗨哟啊发送一封站内信,这种情况下就需要频繁的修改代码,违反开闭原则。而且注册成功之后需要执行的后续操作越来越多,那就会影响到代码的可读性和可维护。
这个时候利用观察者模式进行代码重构,重构后的代码如下;
public interface RegObserver { void handleRegSuccess(long userId);}
public class RegPromotionObserver implements RegObserver { private PromotionService promotionService; // 依赖注入
@Override public void handleRegSuccess(long userId) { promotionService.issueNewUserExperienceCash(userId); }}
public class RegNotificationObserver implements RegObserver { private NotificationService notificationService;
@Override public void handleRegSuccess(long userId) { notificationService.sendInboxMessage(userId, "Welcome..."); }}
public class UserController { private UserService userService; // 依赖注入 private List<RegObserver> regObservers = new ArrayList<>();
// 一次性设置好,之后也不可能动态的修改 public void setRegObservers(List<RegObserver> observers) { regObservers.addAll(observers); }
public Long register(String telephone, String password) { //省略输入参数的校验代码 //省略userService.register()异常的try-catch代码 long userId = userService.register(telephone, password);
for (RegObserver observer : regObservers) { observer.handleRegSuccess(userId);    } return userId; }}
当我们需要添加新的观察者的时候,比如,用户注册成功之后,推送用户注册信息给大数据征信系统,基于这个观察者模式的代码实现,UserController类的register()函数完全不需要修改,只需要添加一个实现了RegObserver接口的类,并且通过setRegObservers函数将它注册到UserController类中即可。
不同的应用场景和需求下,这个模式也有截然不同的实现方式,有同步阻塞的,也有异步非阻塞的方式;有进程内实现方式,也有跨进程的实现方式。

以上是关于设计模式之美-行为型-观察者模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式之美(c++)-笔记-56-观察者模式

设计模式 行为型模式 -- 观察者模式(发布-订阅(Publish/Subscribe)模式)

初探Java设计模式3:行为型模式(策略,观察者等)

Python 设计模式 — 行为型模式 — 观察者模式

Python 设计模式 — 行为型模式 — 观察者模式

行为型模式之对象间的联动(观察者模式)