• 观察者模式-对象间的联动


     有个商城小程序,用户希望当有新品上市的时候能通知他们。这样用户就可以不要时刻盯着小程序了。在这个场景中,用户向小程序订阅了一个服务——发送新品短信。小程序在有新品上线时负责向订阅客户发出这个消息。

    这就是发布-订阅模式,也称观察者模式

    1 观察者模式

    是使用频率最高的设计模式之一。定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并自动更新。

    图 观察者模式UML

    Subject,目标类。是指被观察的对象,在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供了一系列方法来增加和删除观察者对象,同时定义了通知方法notify(),目标类可以是接口,也可以是抽象或具体类。

    ConcreteSubject,具体目标。是目标类的子类,通常包含有经常发生改变的数据。当它当状态发生改变时,向其各个观察者发出通知。同时它还实现了在目标类中定义的抽象业务逻辑方法(如果有)。如果无须扩展目标类,则具体目标类可以省略。

    Observer,观察者。观察者将对观察目标的改变做出反应。观察者一般定义为接口。该接口声明了更新数据的方法update()。

    ConcreteObserver,具体观察者。实现了Observer中声明的update()方法。通常在实现时,可以调用具体目标类的attach()方法将自己添加到目标类的集合或通过detach()方法将自己从目标类的集合中删除。

    1. public interface Observer {
    2. void update(String message);
    3. }
    4. public class MessageSubject {
    5. private final List<Observer> observerList = new ArrayList<>();
    6. public void attach(Observer observer) {
    7. this.observerList.add(observer);
    8. }
    9. public void detach(Observer observer) {
    10. this.observerList.remove(observer);
    11. }
    12. public void notifyObservers(String message) {
    13. for (Observer observer : observerList) {
    14. observer.update(message);
    15. }
    16. }
    17. }
    18. public class AppletMessageSubject extends MessageSubject {
    19. @Override
    20. public void notifyObservers(String message) {
    21. super.notifyObservers(message);
    22. System.out.println("小程序平台日志记录,消息发送成功:" + message);
    23. }
    24. }
    25. public class ApiObserver implements Observer{
    26. @Override
    27. public void update(String message) {
    28. System.out.println("商品推送开始:" + message);
    29. }
    30. }
    31. public class UserObserver implements Observer{
    32. @Override
    33. public void update(String message) {
    34. System.out.println("好的。我知道了,我准备购买:" + message);
    35. }
    36. }
    37. public class ShopWeb {
    38. public static void main(String[] args) {
    39. MessageSubject subject = new AppletMessageSubject();
    40. Observer userObserver = new UserObserver();
    41. Observer apiObserver = new ApiObserver();
    42. subject.attach(userObserver);
    43. subject.attach(apiObserver);
    44. subject.notifyObservers("IPhone 15");
    45. subject.notifyObservers("Mate 16");
    46. }
    47. }
    48. //好的。我知道了,我准备购买:IPhone 15
    49. //商品推送开始:IPhone 15
    50. //小程序平台日志记录,消息发送成功:IPhone 15
    51. //好的。我知道了,我准备购买:Mate 16
    52. //商品推送开始:Mate 16
    53. //小程序平台日志记录,消息发送成功:Mate 16

    1.1 JDK 对观察者模式的支持

    在JDK的java.util包中,提供了Observable类以及Observer接口,它们构成了JDK 对观察者模式的支持。

    图 Observable的域与方法

    图 Observer 接口

    需求:求职者订阅了某boss招聘软件职位发布信息,当有新的职位发布时,会通知给求职者。求职者收到信息后,投递简历。

    1. public class BossObservable extends Observable {
    2. @Override
    3. public void notifyObservers(Object arg) {
    4. super.setChanged();
    5. super.notifyObservers(arg);
    6. System.out.println("记录日志,职位信息推送成功:" + arg);
    7. }
    8. }
    9. public class EmployeeObserver implements Observer {
    10. private String name;
    11. public EmployeeObserver(String name) {
    12. this.name = name;
    13. }
    14. @Override
    15. public void update(Observable o, Object arg) {
    16. System.out.println(name + "。我钟意这个岗位:" + arg);
    17. }
    18. }
    19. public class Market {
    20. public static void main(String[] args) {
    21. Observable bossJob = new BossObservable();
    22. Observer employee1 = new EmployeeObserver("小李");
    23. Observer employee2 = new EmployeeObserver("小吴");
    24. bossJob.addObserver(employee1);
    25. bossJob.addObserver(employee2);
    26. bossJob.notifyObservers("Java 开发");
    27. bossJob.notifyObservers("全栈开发");
    28. }
    29. }
    30. //小吴。我钟意这个岗位:Java 开发
    31. //小李。我钟意这个岗位:Java 开发
    32. //记录日志,职位信息推送成功:Java 开发
    33. //小吴。我钟意这个岗位:全栈开发
    34. //小李。我钟意这个岗位:全栈开发
    35. //记录日志,职位信息推送成功:全栈开发

    2 优缺点

    优点:

    1)在观察目标和观察者之间建立一个抽象的耦合。观察目标只需维持一个抽象观察者集合,无须了解其具体观察者。

    2)观察者模式支持广播通信,观察目标会向所有已注册的观察者对象发送通知。

    缺点:

    1)如果一个观察目标对象有许多观察者,将所有观察者都通知到会花费很多时间。

    2)如果在观察者和观察目标之间存在循环依赖,观察目标会触发它们之间进行循环调用,可能导致系统奔溃。

    3 适用场景

    1)一个对象的改变将导致一个或多个其他对象也发生改变,而并不知道具体有多少对象及具体的对象。

    2)需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象…可以使用观察者模式创建一种链式触发机制。

  • 相关阅读:
    [Docker精进篇] Docker镜像构建和实践 (三)
    redis 管道(pipeline),深入解读
    springboot+springsecurity+elementui博客系统-dsblog
    JavaScript 18 JavaScript 字符串
    elasticsearch安装 及 启动异常解决
    力扣细节题:判断是否为平衡二叉树
    图片链接打不开检测工具-免费链接失败检测软件
    阿里巴巴中国站按图搜索1688商品(拍立淘) API 返回值说明
    数据变换:数据挖掘的准备工作之一
    Pytorch总结七之深度学习的正向、反向传播原理+参数初始化+实战房价预测
  • 原文地址:https://blog.csdn.net/qq_25308331/article/details/133937752