模式说明

对于观察者模式定义是对象之间存在一对多的依赖关系,当一个对象的状态发生变化时,其所有依赖的对象会被自动通知和更新。观察者模式分了被观察者和观察者,而一个被观察者对应多个观察者,当被观察者的状态发生变化时则会通知或更新所有的观察者。

应用场景

在 JavaScript 中存在大量的事件监听,如点击按钮、右键、鼠标在某元素上方悬停事件等,一般可以为这些事件增加多个监听方法,只要存在事件被触发,那么监听的方法就会被调用,在这里,事件就称为了被观察者,所监听的方法就成为了观察者。

有时候我们登录应用的时候会收到登录通知,这是因为我们的这个成功登录的事件触发的消息通知,常见的有微信通知,短信通知等,还有邮件的来信通知也是一样,收到邮件的这个事件触发了来信通知。在这里,登录及来信就是被观察者,而通知则是观察者。

如果一个接口支持异步调用的方式,同样适合使用观察者模式实现。因为客户端调用异步处理的接口时无法确认该接口的处理是否结束,所以在调用异步接口中可以增加回调地址,在异步处理结束后被请求,不管成功还是失败,那么这里的接口处理情况就是被观察者,而回调的地址就是观察者了,只不过这里的观察者只有一个。
image.png

代码实现

现在比较有影响力的微信开发者中心、腾讯开发者中心、钉钉开发者中心都具备大量的事件回调通知设置,以下是通过用户的创建、更新、删除进行通知触发,其中 CallbackManager 是观察者,UserAction 是被观察者。

  1. // 观察者
  2. public class CallbackManager {
  3. Map<String, Runnable> callbacks = new HashMap<>();
  4. public void register(String name, Runnable runnable) {
  5. Objects.requireNonNull(runnable);
  6. callbacks.put(name, runnable);
  7. }
  8. public void remove(String name) {
  9. Objects.requireNonNull(runnable);
  10. callbacks.remove(name);
  11. }
  12. public void notify(String name) {
  13. Objects.requireNonNull(name);
  14. CompletableFuture.runAsync(callbacks.get(name));
  15. }
  16. public void notifyAll() {
  17. for (Runnalbe runnalbe : callbacks.values()) {
  18. CompletableFuture.runAsync(runnalbe);
  19. }
  20. }
  21. }
  22. // 被观察者
  23. public class UserAction {
  24. CallbackManager callbackManager ...;
  25. public void createUser() {
  26. // ...
  27. callbackManager.notify("CreateUser");
  28. }
  29. public void updateUser() {
  30. // ...
  31. callbackManager.notify("UpdateUser");
  32. }
  33. public void deleteUser() {
  34. // ...
  35. callbackManager.notify("DeleteUser");
  36. }
  37. }