设计模式 - Observer Pattern 观察者模式

文章目录

定义

观察者模式是行为型模式的一种,它定义对象间的一种一对多的依赖关系,使得每当一个对象改变状态,它的所有依赖都会收到通知并且自动更新状态。

简单来说就是:当一个行为发生时传递信息给另外一个用户接收做出相应的处理,它们之间其实没有什么直接的关联。

观察者模式的实现构成

构成

  1. 主题(Subject) :抽象主题,提供方法来增加和删除观察者,当自身状态发生改变时,通知所有观察者。

  2. 观察者(Observer) :抽象观察者,用于接收主题状态更新的通知。

  3. 具体主题(Concrete Subject) :实现主题接口、在其内部状态发生改变时,通知所有注册的观察者。

  4. 具体观察者(Concrete Observer):实现观察者接口、在接收到主题的通知时更新自身状态。

UML图

观察者模式的代码实现

场景

假设我们有一个股票价格监控系统,不同的模块(图表模块、统计模块和警报模块),它们需要实时更新股票价格信息。当股票价格发生变化时,这些模块就立即可以获取到通知并且可以进行更新显示。

代码实现

观察者接口

java 复制代码
// 观察者接口,定义更新方法
interface Observer {
	// 当主题状态变化时调用此方法通知观察者。
    void update(double price);
}

具体观察者

java 复制代码
// 具体观察者:图表模块
class ChartDisplay implements Observer {
    @Override
    public void update(double price) {
        System.out.println("图表模块更新股票价格: " + price);
    }
}

// 具体观察者:统计模块
class StatisticsDisplay implements Observer {
    @Override
    public void update(double price) {
        System.out.println("统计模块更新股票价格: " + price);
    }
}

// 具体观察者:警报模块
class AlertSystem implements Observer {
    @Override
    public void update(double price) {
        if (price > 100.0) {
            System.out.println("警报!股票价格超过100元: " + price);
        }
    }
}

主题接口

java 复制代码
// 主题接口,定义增加、删除观察者及通知方法,用于管理和通知观察者。
interface Subject {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

具体主题

java 复制代码
// 具体主题:实现了Subject,用来维护观察者列表并在价格变化时通知所有观察者。
class StockPrice implements Subject {
    private List<Observer> observers;
    private double price;

    public StockPrice() {
        observers = new ArrayList<>();
    }

    @Override
    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(price);
        }
    }

    // 设置新价格并通知观察者
    public void setPrice(double price) {
        this.price = price;
        notifyObservers();
    }
}

客户端代码

java 复制代码
// 客户端代码
public class ObserverPatternDemo {
    public static void main(String[] args) {
        // 创建具体主题
        StockPrice stockPrice = new StockPrice();

        // 创建具体观察者
        ChartDisplay chartDisplay = new ChartDisplay();
        StatisticsDisplay statisticsDisplay = new StatisticsDisplay();
        AlertSystem alertSystem = new AlertSystem();

        // 注册观察者
        stockPrice.addObserver(chartDisplay);
        stockPrice.addObserver(statisticsDisplay);
        stockPrice.addObserver(alertSystem);

        // 更新股票价格
        stockPrice.setPrice(95.0);
        System.out.println();

        stockPrice.setPrice(105.0);
    }
}

总结

优点

  1. 解耦:主题只需知道观察者实现了某个接口,不需要知道具体实现细节,双方可以独立变化。

  2. 目标与观察者之间建立了一套触发机制。

缺点

  1. 当观察者对象很多时,通知的发布会花费很长时间,影响程序的效率。

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

应用场景

跨系统的消息交换场景,如消息队列,事件总线的处理机制

其他设计模式文章:

相关推荐
xyliiiiiL1 分钟前
一文总结常见项目排查
java·服务器·数据库
shaoing3 分钟前
MySQL 错误 报错:Table ‘performance_schema.session_variables’ Doesn’t Exist
java·开发语言·数据库
腥臭腐朽的日子熠熠生辉1 小时前
解决maven失效问题(现象:maven中只有jdk的工具包,没有springboot的包)
java·spring boot·maven
ejinxian1 小时前
Spring AI Alibaba 快速开发生成式 Java AI 应用
java·人工智能·spring
杉之1 小时前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat
圈圈编码1 小时前
Spring Task 定时任务
java·前端·spring
俏布斯2 小时前
算法日常记录
java·算法·leetcode
27669582922 小时前
美团民宿 mtgsig 小程序 mtgsig1.2 分析
java·python·小程序·美团·mtgsig·mtgsig1.2·美团民宿
爱的叹息2 小时前
Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比
java·redis·spring
程序猿chen2 小时前
《JVM考古现场(十五):熵火燎原——从量子递归到热寂晶壁的代码涅槃》
java·jvm·git·后端·java-ee·区块链·量子计算