重学Java设计模式-观察者模式

1. 定义与基本概念

定义

观察者模式其中一个对象(称为“主题”或“主体”)维护一组依赖于它的对象(称为“观察者”),并在其状态发生变化时通知这些观察者

基本概念

主题(Subject)
  • 定义:主题是被观察的对象,它维护一个观察者的列表,并在状态发生变化时通知这些观察者。

  • 角色

    • 注册观察者(registerObserver(Observer observer)
    • 移除观察者(removeObserver(Observer observer)
    • 通知观察者(notifyObservers()
观察者(Observer)
  • 定义:观察者是对主题感兴趣的对象,它需要实现一个接口,以便在主题状态变化时接收通知。

  • 角色

    • 更新方法(update()):用于接收主题状态变化的通知。
具体主题(Concrete Subject)
  • 定义:具体主题是实现主题接口的具体类,它包含状态数据,并在状态变化时调用通知观察者的方法。
  • 示例:天气数据提供者,它包含温度、湿度等数据。
具体观察者(Concrete Observer)
  • 定义:具体观察者是实现观察者接口的具体类,它根据主题的状态变化进行相应的更新。
  • 示例:显示当前天气的用户界面组件。

2. 场景案例

假设一个抖音博主(Subject)发布视频通知粉丝(Observer)的场景,博主发布视频通知所有粉丝。

3. 代码一把梭

定义博主类

 

typescript

代码解读

复制代码

/** * 抖音博主 */ public class DouyinBlogger {    private String latestVideoTitle; ​    // 模拟发布新视频    public void publishNewVideo(String title) {        this.latestVideoTitle = title;        System.out.println("博主发布了新视频: " + title);   } ​    // 通知粉丝    public void notifyFollower(String userName) {        System.out.println(userName + ", 快来看我的新视频: " + latestVideoTitle);   } ​ ​    public String getLatestVideoTitle() {        return latestVideoTitle;   } ​    public void setLatestVideoTitle(String latestVideoTitle) {        this.latestVideoTitle = latestVideoTitle;   } }

发布视频->通知粉丝测试

 

java

代码解读

复制代码

@Test public void shit() {    DouyinBlogger douyinBlogger = new DouyinBlogger();    douyinBlogger.publishNewVideo("国足五年来首次对日本破门"); ​    douyinBlogger.notifyFollower("小王");    douyinBlogger.notifyFollower("小李");    douyinBlogger.notifyFollower("小张");    douyinBlogger.notifyFollower("小杨");    douyinBlogger.notifyFollower("小明");    douyinBlogger.notifyFollower("小红");    douyinBlogger.notifyFollower("小赵");    douyinBlogger.notifyFollower("小何");    douyinBlogger.notifyFollower("其他N个粉丝"); }

测试结果

 

makefile

代码解读

复制代码

博主发布了新视频: 国足五年来首次对日本破门 小王, 快来看我的新视频: 国足五年来首次对日本破门 小李, 快来看我的新视频: 国足五年来首次对日本破门 小张, 快来看我的新视频: 国足五年来首次对日本破门 小杨, 快来看我的新视频: 国足五年来首次对日本破门 小明, 快来看我的新视频: 国足五年来首次对日本破门 小红, 快来看我的新视频: 国足五年来首次对日本破门 小赵, 快来看我的新视频: 国足五年来首次对日本破门 小何, 快来看我的新视频: 国足五年来首次对日本破门 其他粉丝, 快来看我的新视频: 国足五年来首次对日本破门

4. 观察者模式重构代码

工程结构

 

css

代码解读

复制代码

├── src │   ├── main │   │   └── java │   │       └── com │   │           └── bbbwdc │   │               └── observer │   │                   ├── pattern │   │                   │   ├── observer │   │                   │   │   ├── IObserver.java │   │                   │   │   ├── XiaohongObserver.java │   │                   │   │   ├── XiaoliObserver.java │   │                   │   │   ├── XiaomingObserver.java │   │                   │   │   ├── XiaowangObserver.java │   │                   │   │   ├── XiaoyangObserver.java │   │                   │   │   └── XiaozhangObserver.java │   │                   │   └── subject │   │                   │       ├── DouyinBloggerSubject.java │   │                   │       └── ISubject.java

定义主题接口

 

csharp

代码解读

复制代码

/** * 主题接口 */ public interface ISubject {    /**     * 注册观察者     * @param observer     */    void registerObserver(IObserver observer); ​    /**     * 移除观察者     * @param observer     */    void removeObserver(IObserver observer);    /**     * 通知观察者     */    void notifyObservers(); }

定义观察者接口

 

arduino

代码解读

复制代码

/** * 观察者接口 */ public interface IObserver {        void update(String videoTitle); }

实现主题接口(抖音博主)

 

typescript

代码解读

复制代码

/** * 抖音博主 */ public class DouyinBloggerSubject implements ISubject {    // 粉丝列表    private List<IObserver> followers;    // 最新视频标题    private String latestVideoTitle; ​    public DouyinBloggerSubject() {        followers = new ArrayList<>();   } ​    @Override    public void registerObserver(IObserver observer) {        followers.add(observer);   } ​    @Override    public void removeObserver(IObserver observer) {        followers.remove(observer);   } ​    @Override    public void notifyObservers() {        for (IObserver follower : followers) {            follower.update(latestVideoTitle);       }   } ​    // 模拟发布新视频    public void publishNewVideo(String title) {        this.latestVideoTitle = title;        System.out.println("博主发布了新视频: " + title);        notifyObservers(); // 通知所有粉丝   }

实现观察者接口(粉丝)

有多个粉丝,这里仅拿小明作为代码示例。在实际场景中,一个主题可能有很多的观察者。

 

typescript

代码解读

复制代码

public class XiaomingObserver implements IObserver {    @Override    public void update(String videoTitle) {        String name = "小明";        System.out.println(name + ", 快来看我的新视频: " + videoTitle);   } }

测试

 

ini

代码解读

复制代码

@Test public void pattern() {    DouyinBloggerSubject blogger = new DouyinBloggerSubject();    blogger.registerObserver(new XiaowangObserver());    blogger.registerObserver(new XiaoliObserver());    blogger.registerObserver(new XiaozhangObserver());    blogger.registerObserver(new XiaoyangObserver());    blogger.registerObserver(new XiaomingObserver());    XiaohongObserver xiaohongObserver = new XiaohongObserver();    blogger.registerObserver(xiaohongObserver);    blogger.publishNewVideo("国足五年来首次对日本破门"); ​    blogger.removeObserver(xiaohongObserver);        blogger.publishNewVideo("李子柒复出"); }

测试结果

 

makefile

代码解读

复制代码

博主发布了新视频: 国足五年来首次对日本破门 小王, 快来看我的新视频: 国足五年来首次对日本破门 小李, 快来看我的新视频: 国足五年来首次对日本破门 小张, 快来看我的新视频: 国足五年来首次对日本破门 小杨, 快来看我的新视频: 国足五年来首次对日本破门 小明, 快来看我的新视频: 国足五年来首次对日本破门 小红, 快来看我的新视频: 国足五年来首次对日本破门 博主发布了新视频: 李子柒复出 小王, 快来看我的新视频: 李子柒复出 小李, 快来看我的新视频: 李子柒复出 小张, 快来看我的新视频: 李子柒复出 小杨, 快来看我的新视频: 李子柒复出 小明, 快来看我的新视频: 李子柒复出

5. 观察者模式的优缺点

优点

  • 解耦合
  • 灵活性和可扩展性
  • 动态订阅和取消订阅
  • 符合单一职责原则

缺点

  • 可能导致内存泄漏
  • 过多的通知可能影响性能
  • 复杂性增加

6. 观察者模式的应用场景

  • 用户界面事件处理
  • 数据变化通知
  • 事件驱动架构
  • 实时数据更新(如股票价格、天气信息)
  • 消息推送系统

7. 观察者模式和发布订阅模式的区别

在学习观察者模式时,总感觉它和发布订阅模式很像,两者傻傻分不清楚

7.1 定义

观察者模式

观察者模式是一种设计模式,其中一个对象(主题或被观察者)维护一组依赖于它的对象(观察者),并在其状态发生变化时自动通知这些观察者。

发布-订阅模式

发布-订阅模式是一种更松耦合的架构模式,其中发布者(发布事件的对象)与订阅者(接收事件的对象)之间没有直接的引用关系,而是通过一个中介(如消息代理或事件总线)进行通信。

7.2 触发机制

观察者模式

  • 观察者直接注册到主题上,主题在状态变化时主动调用观察者的更新方法。
  • 主题和观察者之间有直接的依赖关系。

发布-订阅模式

  • 发布者将消息或事件发布到中介,由中介负责将消息分发给所有订阅者。
  • 发布者和订阅者之间没有直接的依赖关系,通常通过中介进行解耦。

7.3 关系

观察者模式

  • 一对多关系:一个主题可以有多个观察者。
  • 观察者与主题之间是紧耦合的,观察者需要知道主题的存在。

发布-订阅模式

  • 多对多关系:一个发布者可以有多个订阅者,一个订阅者可以订阅多个发布者的消息。
  • 发布者与订阅者之间完全解耦,彼此之间不需要了解对方的存在。

7.4 通知方式

观察者模式

  • 通常是同步通知,主题在状态变化时立即通知所有观察者。
  • 观察者会在接收到通知后立即执行更新操作。

发布-订阅模式

  • 通常支持异步通知,发布者可以在发布消息后继续执行,不必等待所有订阅者处理完毕。
  • 订阅者可以在合适的时机处理接收到的消息。

7.5 用途

观察者模式

  • 适用于对象之间有直接依赖关系的场景,例如 GUI 事件处理、实时数据更新等。

发布-订阅模式

  • 适用于更复杂的事件驱动架构,特别是在需要解耦、灵活性和异步处理的场景中,例如消息队列、事件总线等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值