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

23种设计模式-行为型模式-观察者

文章目录

  • 简介
  • 问题
  • 解决
    • 代码
    • 关键实现说明
  • 总结

简介

观察者是一种行为设计模式, 允许你定义一种订阅通知机制, 可在事件发生时通知多个“观察/订阅”该对象的其他对象。

问题

假如你有两种类型的对象: 顾客和商店。顾客对某个新品非常感兴趣,他可以每天来商店看产品是否到货。但如果商品尚未到货时,顾客就会空手而归。

前往商店和发送垃圾邮件
或者,每次产品到货时,商店可以向所有顾客发送邮件。这样,部分顾客就无需反复前往商店了,但也可能会惹恼对新品没有兴趣的其他顾客。
我们似乎遇到了一个矛盾:要么让顾客浪费时间检查产品是否到货,要么让商店去通知所有顾客。

解决

拥有被关注状态的对象,比如商店,通常被称为目标,由于它要在自身状态改变时通知给其他对象,我们也将其称为发布者(publisher)。 所有关注发布者状态变化的其他对象被称为订阅者(subscribers),比如顾客。
观察者模式建议你为发布者类添加订阅机制,让每个对象都能订阅或取消订阅发布者的事件。这个机制包括 :

  1. 一个成员变量,它是一个列表,用于存储所有订阅者对象的引用。
  2. 几个用于添加或删除列表中订阅者的公有方法。

订阅机制允许对象订阅事件通知
如果发生了发布者事件,它就要遍历订阅者并调用其对象的特定通知方法。
实际应用中可能会有十几个不同的订阅者类订阅同一个发布者类的事件,你不希望发布者与所有这些类相耦合。此外如果别人也会订阅这个发布者类, 你甚至不知道这些订阅者类是什么。
因此,所有订阅者都必须实现同样的接口,发布者仅通过该接口与订阅者交互。接口中必须声明通知方法及其参数,这样发布者在发出通知时还能传递一些上下文数据。
发布者调用订阅者对象中的特定通知方法来通知订阅者
如果你的应用中有多个不同类型的发布者,且希望订阅者可兼容所有发布者,那么你甚至可以进一步让所有订阅者遵循同样的接口。该接口仅需定义几个订阅方法即可。这样订阅者就能在不与具体发布者类 耦合的情况下通过接口订阅发布者的状态变化通知。

代码

// Publisher 接口
interface StorePublisher {
    void subscribe(CustomerSubscriber subscriber);
    void unsubscribe(CustomerSubscriber subscriber);
    void notifySubscribers(String product);
}

// 具体 Publisher 类
class IPhoneStore implements StorePublisher {
    private List<CustomerSubscriber> customers = new ArrayList<>();
    
    @Override
    public void subscribe(CustomerSubscriber subscriber) {
        customers.add(subscriber);
    }
    
    @Override
    public void unsubscribe(CustomerSubscriber subscriber) {
        customers.remove(subscriber);
    }
    
    @Override
    public void notifySubscribers(String product) {  // 触发所有订阅者更新 
        for (CustomerSubscriber customer : customers) {
            customer.update(product);
        }
    }
    
    public void restockProduct(String product) {
        System.out.println("新品到货:" + product);
        notifySubscribers(product);
    }
}

// Subscriber 接口
interface CustomerSubscriber {
    void update(String product);
}

// 具体 Subscriber 类
class PremiumCustomer implements CustomerSubscriber {
    private String name;

    public PremiumCustomer(String name) {
        this.name = name;
    }

    @Override
    public void update(String product) {  // 实现标准通知接口
        System.out.println("[尊享客户]" + name + ",您关注的" + product + "已到店");
    }
}

// Client 客户端配置
public class ObserverDemo {
    public static void main(String[] args) {
        IPhoneStore store = new IPhoneStore();
        
        CustomerSubscriber alice = new PremiumCustomer("Alice");
        CustomerSubscriber bob = new PremiumCustomer("Bob");
        
        // 动态添加订阅
        store.subscribe(alice);
        store.subscribe(bob);
        
        // 模拟到货事件
        store.restockProduct("iPhone15");
        
        // 动态移除订阅
        store.unsubscribe(bob);
        store.restockProduct("iPhone15 Pro");
    }
}

关键实现说明

  1. IPhoneStore 作为具体发布者,实现订阅管理和产品到货通知
  2. 通过接口解耦使得新订阅者类型可以扩展而不影响发布者
  3. 客户端通过subscribe()/unsubscribe()动态维护订阅列表

总结

在这里插入图片描述

  1. 发布者(Publisher)会向其他对象发送事件。事件会在发布者自身状态改变或执行特定行为后发生。发布者中包含一个加入新订阅者和当前删除旧订阅者的方法。
  2. 当新事件发生时,发送者会遍历订阅列表并调用每个订阅者对象 的通知方法。 这个方法是在订阅者接口中声明的。
  3. 订阅者(Subscriber)接口声明了通知接口。在绝大多数情况下 这个接口只包含一个 update 更新 方法。 该方法可以拥有多个参 数, 让发布者能在事件发生时传递事件的详细信息。
  4. 具体订阅者(Concrete Subscribers) 可以执行一些操作来回应发布者的通知。所有具体订阅者类都实现了同样的接口,所以发布者不需要与具体类相耦合。
  5. 订阅者通常需要一些上下文信息来正确地处理更新。所以发布者通常会把一些上下文数据作为通知方法的参数。 发布者也可以把自己作为参数进行传递,使订阅者直接获取所需的数据
  6. 客户端(Client)会分别创建发布者和订阅者对象,然后向发布者注册订阅者。

相关文章:

  • Photoshop2025最新版v26超详细图文安装教程(附安装包)
  • 【大模型深度学习】提示学习:Prefix tuning 、P-tuning v2、P-tuning 到底有什么区别?
  • 【Python】Python 100题 分类入门练习题 - 新手友好
  • 模板引擎Freemarker使用教程
  • LabVIEW真空度监测与控制系统
  • 【RH124】第六章 管理本地用户和组
  • 启山智软的b2c前端页面设计
  • 【kind管理脚本-1】便捷使用 kind 创建、删除、管理集群脚本
  • CANoe CAPL——CANoe IL函数
  • vue3项目中模拟AI的深度思考功能
  • svelte+vite+ts+melt-ui从0到1完整框架搭建
  • 我的第一个开源小项目:内网文件传输工具技术解析
  • Android设置adjustResize时无法生效 解决办法
  • Go 错误处理
  • 单轨小车悬挂输送机安全规程
  • 通过学习opencv图像库编程借助第三方库函数完成一个综合程序设计
  • moviepy学习使用笔记
  • 浅层神经网络:全面解析(扩展)
  • 【OSG学习笔记】Day 1: OSG初探——环境搭建与第一个3D窗口
  • 【SpringCloud】构建分布式系统的利器
  • 免费网站登陆模板/搜索引擎营销方案例子
  • 南川网站建设/广告推广app
  • 福州网站建设资讯/长春seo公司哪家好
  • 网站开发er图/西安百度推广优化公司
  • 最专业的外贸网站建设/资源搜索引擎
  • 东莞网站建设案例/seo实战培训班