当前位置: 首页 > news >正文

23种设计模式-观察者(Observer)设计模式

观察者设计模式

  • 🚩什么是观察者模式?
  • 🚩观察者设计模式的特点
  • 🚩观察者设计模式的结构
  • 🚩观察者设计模式的优缺点
  • 🚩观察者设计模式的Java实现
  • 🚩代码总结
  • 🚩总结

🚩什么是观察者模式?

观察者模式(Observer Pattern) 是一种 行为型设计模式,它定义了一种 一对多的依赖关系,使得 一个对象(被观察者) 的状态发生变化时,所有依赖它的 观察者 都会收到通知并自动更新。

使用场景

  • 事件驱动系统(如 GUI 事件监听)

  • 消息订阅-发布系统

  • 数据同步更新(如缓存更新、数据库同步等)

  • MVC 设计模式中的视图更新

🚩观察者设计模式的特点

  • 解耦观察者与被观察者:被观察者只关心自身状态的变化,不关心谁在监听它。

  • 自动通知:状态变更后,所有观察者都会收到通知。

  • 动态注册和取消:观察者可以随时订阅或取消订阅。

🚩观察者设计模式的结构

观察者模式主要由以下角色组成:

  • Subject(被观察者):维护观察者列表,并在状态变化时通知所有观察者。

  • ConcreteSubject(具体被观察者):实际的被观察对象,实现 Subject 接口。

  • Observer(观察者接口):定义一个 update() 方法,用于接收被观察者的通知。

  • ConcreteObserver(具体观察者):实现 Observer 接口,接收通知并更新自身状态。

🚩观察者设计模式的优缺点

✅ 优点

  • 解耦被观察者和观察者,提高代码的灵活性。

  • 支持动态扩展,可以在运行时添加或移除观察者。

  • 符合开闭原则,可以增加新的观察者而无需修改被观察者。

❌ 缺点

  • 可能会有性能问题,如果观察者过多,通知开销可能较大。

  • 通知顺序不可控,多个观察者的执行顺序可能会有影响。

🚩观察者设计模式的Java实现

代码地址:GitHub

  • 先创建Observer(观察者)接口
/**
 * @author hanso
 * @description: 观察者接口
 * @date 2025-03-25 23:40:16
 * @version: 1.0
 */
public interface Observer { // 观察者接口
    public void update(); // 收到通知 更新观察者的状态
}
  • 创建被观察者接口Subject
/**
 * @author hanso
 * @description: 被观察者接口
 * @date 2025-03-25 23:39:08
 * @version: 1.0
 */
public interface Subject {// 目标
    public void Attach(Observer observer);// 添加观察者
    public void Detach(Observer observer);// 删除观察者
    public void Notify();// 状态改变后 通知所有观察者
    public void setState(String state);// 设置状态(改变状态)
    public String getState();// 获取状态
}
  • 创建具体的被观察者类(目标类)实现Subject接口
/**
 * @author hanso
 * @description: 具体被观察者
 * @date 2025-03-25 23:41:58
 * @version: 1.0
 */
public class ConcreteSubject implements Subject {
    private String name;
    private String state;

    private List<Observer> observerList;

    public ConcreteSubject(String name) {
        state = "未更新";
        this.name = name;

        observerList = new ArrayList<Observer>();
    }

    @Override
    public void Attach(Observer observer) {
        observerList.add(observer);
    }

    @Override
    public void Detach(Observer observer) {
        observerList.remove(observer);
    }

    @Override
    public void Notify() {
        // for (遍历对象类型 对象名 : 遍历对象)
        for (Observer observer : observerList) {
            observer.update();
        }
    }

    @Override
    public void setState(String state) {
        this.state = state;

        System.out.println(name + "的状态发生变化,变化后的状态为:" + state);
        Notify();
    }

    @Override
    public String getState() {
        return state;
    }
}
  • 创建具体的观察者类ConcreteObserver实现Observer接口
/**
 * @author hanso
 * @description: 具体观察者
 * @date 2025-03-25 23:44:32
 * @version: 1.0
 */
public class ConcreteObserver implements Observer {
    private String name;
    private String state;

    private Subject subject;

    public ConcreteObserver(String name, Subject subject) {
        this.name = name;

        this.subject = subject;
        subject.Attach(this);

        state = subject.getState();
    }

    @Override
    public void update() {
        System.out.println(name + "收到通知");
        state = subject.getState(); // 让当前观察者的状态 和 改变了状态之后的目标的状态保持一致

        System.out.println(name + "改变后的状态为:" + state);
    }
}
  • 测试观察者设计模型
/**
 * @author hanso
 * @description: 测试观察者模式
 * @date 2025-03-25 23:46:15
 * @version: 1.0
 */
public class ObserverPattern {
    public static void main(String[] args) {
        Subject subjectA = new ConcreteSubject("目标A");

        ConcreteObserver observerB = new ConcreteObserver("张三", subjectA);
        ConcreteObserver observerC = new ConcreteObserver("李四", subjectA);
        ConcreteObserver observerD = new ConcreteObserver("王五", subjectA);

        subjectA.setState("更新了");

        System.out.println("======================================");

        subjectA.Detach(observerD);

        subjectA.setState("停更了");
    }
}

📌 运行结果

在这里插入图片描述

🚩代码总结

  • ConcreteSubject(具体被观察者) 维护观察者列表,并在状态更新时通知所有观察者。

  • ConcreteObserver(具体观察者) 在被观察者状态变化时,自动更新自身状态。

  • 使用 Attach() Detach()方法动态添加/移除观察者。

🚩总结

  • 观察者模式 适用于 事件驱动消息广播数据同步 等场景。

  • 解耦设计,被观察者和观察者独立,可以动态扩展。

创作不易,不妨点赞、收藏、关注支持一下,各位的支持就是我创作的最大动力❤️

在这里插入图片描述

相关文章:

  • django入门教程之自定义中间件【七】
  • leetcode:136. 只出现一次的数字(python3解法)
  • python 格式化利器
  • 一文读懂Sql Server读写分离和分库分表
  • 鼠标在客户区内按下左键和双击右键
  • 光谱范围与颜色感知的关系
  • Spring学习笔记05——Spring Boot的文件结构2(POJO类)
  • 基于 PHP 内置类及函数的免杀 WebShell
  • 【MySQL】mysql日志文件
  • OpenCV图像拼接(3)图像拼接类cv::detail::MultiBandBlender
  • 前端学习笔记--CSS
  • 【机器学习】线性回归和逻辑回归的区别在哪?
  • 【零基础JavaScript入门 | Day7】三大交互案例深度解析|从DOM操作到组件化开发
  • Netty——I/O 线程模型
  • 最长连续子序列和的所含元素 -- Kadane算法拓展
  • 【C++网络编程】第8篇:协议设计与序列化(Protobuf、FlatBuffers)
  • 流式ETL配置指南:从MySQL到Elasticsearch的实时数据同步
  • 【设计模式】工厂模式
  • 信息学奥赛一本通 1514:【例 2】最大半连通子图 | 洛谷 P2272 [ZJOI2007] 最大半连通子图
  • vue watch数据监听
  • 西宁市企业建站专业/网络营销手段
  • 郑州网站建设多少钱/成都网站seo诊断
  • 定制手机网站建设/百度收录方法
  • 企业网站建设策划书1万字/百度竞价培训班
  • 做网站怎么投放广告/做百度推广的网络公司
  • 52麻将官方网站做代理/b2b平台排名