跳至正文
来两杯美式
返回

设计模式之观察者模式:一对多依赖,状态变更自动通知

By 来两杯美式
发布于

这是 2020 年 7 月整理的设计模式专题第十二篇。观察者模式是”发布-订阅”思想的鼻祖——对象状态一变,所有关注它的对象自动收到通知。MQ、事件监听、消息推送都是它的延伸。

简单说明

观察者模式(Observer Pattern):定义了对象之间的一对多依赖,让多个观察者对象同时监听某一个主题对象

主题(被观察者)──> 通知 ──> 观察者1
      │                        ├──> 观察者2
      │                        └──> 观察者3
(一对多:一个主题,多个观察者,变化即广播)

代码实现

以”课程被提问、老师收到通知”为例:

/**
 * 描述:课程问题实体类
 */
@Data
public class Question {
    private Question() {
    }

    public Question(String desc, String username) {
        this.desc = desc;
        this.username = username;
    }

    /** 问题描述 */
    private String desc;
    /** 提问人 */
    private String username;
}

/**
 * 描述:课程,继承被观察者对象
 */
@Data
public class Course extends Observable {
    private String courseName;

    public Course(String courseName) {
        this.courseName = courseName;
    }

    public void hasQuestion(Question question) {
        setChanged();             // 标记状态已改变
        notifyObservers(question); // 广播通知所有观察者
    }
}

/**
 * 描述:老师,观察者,观察课程是否被提问
 */
public class Teacher implements Observer {
    private String teacherName;

    public Teacher(String teacherName) {
        this.teacherName = teacherName;
    }

    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof Course) {
            Course course = (Course) o;
            Question question = (Question) arg;
            System.out.println(teacherName + "老师您好,您的课程" + course.getCourseName() + ""
                    + question.getUsername() + "同学提问:" + question.getDesc());
        }
    }
}

public class ObserverTest {
    public static void main(String[] args) {
        Course course = new Course("Java架构师");
        Teacher teacher = new Teacher("zhangsan");
        course.addObserver(teacher);
        course.hasQuestion(new Question("final怎么用?", "李二狗"));
    }
}

核心三要素

  1. 被观察者继承 Observable:拥有添加/删除观察者、通知的能力;
  2. setChanged() + notifyObservers(arg):先标记状态变化,再广播(arg 为传递的数据);
  3. 观察者实现 Observer:实现 update(o, arg) 接收通知。

注:JDK 的 Observable/Observer 在 Java 9 已标记废弃,生产环境更推荐手写观察者接口或使用事件总线/Spring 事件。核心思想不变:主题持有观察者列表,变化时遍历通知

观察者模式的价值

对比项传统轮询观察者模式
获取变化观察者主动反复查询主题主动推送通知
耦合观察者依赖主题内部细节主题只依赖抽象观察者接口
扩展新增关注者要改业务代码新增观察者只加一个类

抽象耦合:主题(Course)只认识 Observer 接口,不认识具体的 Teacher。新增一种观察者(比如”助教""管理员”)时,主题代码完全不用改——只需实现 Observer 接口并 addObserver。

广播通信:一个主题可以被多个观察者监听,notifyObservers 一次通知所有观察者;同一个观察者也可以监听多个主题

适用场景与优缺点

适用场景

优点

缺点

现实中的应用

场景说明
GUI 事件监听按钮点击、鼠标移动,ActionListener
Spring 事件ApplicationEvent + @EventListener 发布订阅
MQ生产者发布消息,消费者订阅(观察者思想的分布式版)
ServletRequestListener请求创建/销毁监听
RxJava / 响应式编程数据流观察者模式

小结


分享这篇文章:
通过邮件分享这篇文章✓ 链接已复制
查看系列全部文章
  1. 01.软件设计原则:SOLID + KISS / YAGNI / LOD 全景
  2. 02.设计模式之原型模式,及深浅拷贝
  3. 03.设计模式之工厂模式:简单工厂、工厂方法与抽象工厂
  4. 04.设计模式之建造者模式:复杂对象的组装艺术
  5. 05.设计模式之适配器模式:让不兼容的接口协同工作
  6. 06.设计模式之桥接模式:抽象与实现分离,各自独立变化
  7. 07.设计模式之装饰者模式:动态增强,比继承更有弹性
  8. 08.设计模式之代理模式:静态代理与 JDK 动态代理
  9. 09.设计模式之外观模式:统一门面,简化子系统调用
  10. 10.设计模式之享元模式:共享细粒度对象,降低内存占用
  11. 11.设计模式之策略模式:算法家族,自由切换
  12. 12.设计模式之模板方法模式:固定骨架,可变步骤
  13. 13.设计模式之观察者模式:一对多依赖,状态变更自动通知
  14. 14.设计模式之责任链模式:请求逐级传递,动态组合处理者
  15. 15.设计模式之状态模式:状态变,行为变
  16. 16.设计模式之迭代器模式:不暴露内部实现,顺序访问集合

上一篇
Docker 核心概念与安装:镜像、容器、仓库、Dockerfile
下一篇
Docker 入门:为什么容器化是 AI 时代的必备技能