2025/10/17日 每日总结 设计模式实践:观察者模式之股票价格提醒案例解析
设计模式实践:观察者模式之股票价格提醒案例解析
在软件开发中,经常需要处理“一个对象状态变化,多个相关对象需同步响应”的场景。观察者模式通过定义“被观察者-观察者”的一对多依赖关系,让被观察者状态变化时自动通知所有观察者,实现状态同步与解耦。本文将通过股票价格涨跌提醒的实际场景,详细拆解观察者模式的实现逻辑与应用价值。
一、实验背景与需求
本次实践的核心需求是实现股票价格变动提醒系统,具体规则如下:
-
被观察者(股票):价格上涨或下跌5%时,自动通知所有关注它的观察者(股民)
-
观察者(股民):收到价格上涨通知时执行“买股票”操作,收到价格下跌通知时执行“大哭一场”操作
-
支持动态添加/移除观察者(股民可随时关注/取消关注股票)
-
被观察者与观察者解耦,互不直接依赖
二、观察者模式核心结构
观察者模式的关键在于“被观察者”维护观察者列表并提供通知接口,“观察者”实现响应接口,接收通知后执行对应逻辑。本次案例的结构设计如下:
1. 核心组件划分
| 组件类型 | 具体实现 | 职责描述 |
|---|---|---|
| 抽象观察者(Observer) | Observer 接口 | 定义观察者的响应接口(价格上涨/下跌时的行为) |
| 具体观察者(ConcreteObserver) | Investor 类(股民) | 实现抽象观察者接口,具体实现“买股票”和“大哭”逻辑 |
| 抽象被观察者(Subject) | Subject 抽象类 | 定义被观察者的核心接口(添加/移除观察者、通知观察者),维护观察者列表 |
| 具体被观察者(ConcreteSubject) | Stock 类(股票) | 实现抽象被观察者接口,触发价格变动时通知所有观察者 |
2. 类图结构
┌─────────────────┐
│ Observer │ ← 抽象观察者(股民接口)
├─────────────────┤
│ + buy(): void │ ← 价格上涨时的响应
│ + cry(): void │ ← 价格下跌时的响应
└─────────────────┘
▲
│
┌───────────────┐
│ Investor │ ← 具体观察者(股民)
├───────────────┤
│ + buy(): void │ → 实现“买股票”逻辑
│ + cry(): void │ → 实现“大哭一场”逻辑
└───────────────┘
┌─────────────────┐
│ Subject │ ← 抽象被观察者(股票接口)
├─────────────────┤
│ - observers: List<Observer> │ ← 维护观察者列表
├─────────────────┤
│ + abstract attach(observer: Observer): void │ ← 添加观察者(关注股票)
│ + abstract detach(observer: Observer): void │ ← 移除观察者(取消关注)
│ + abstract up(): void │ ← 价格上涨时通知观察者
│ + abstract down(): void │ ← 价格下跌时通知观察者
└─────────────────┘
▲
│
┌───────────────┐
│ Stock │ ← 具体被观察者(股票)
├───────────────┤
│ + attach(observer: Observer): void │ → 实现添加观察者
│ + detach(observer: Observer): void │ → 实现移除观察者
│ + up(): void │ → 价格上涨,通知所有观察者执行buy()
│ + down(): void │ → 价格下跌,通知所有观察者执行cry()
└───────────────┘
三、完整实现代码(Java)
1. 抽象观察者:Observer.java
/**
* 抽象观察者接口:定义股民的响应行为
*/
public interface Observer {
// 股票上涨时的响应:买股票
void buy();
// 股票下跌时的响应:大哭一场
void cry();
}
### 2. 抽象被观察者:Subject.java
```java
import java.util.ArrayList;
/**
* 抽象被观察者类:定义股票的核心接口
*/
public abstract class Subject {
// 维护关注当前股票的观察者列表
protected ArrayList<Observer> observers = new ArrayList<>();
// 添加观察者(股民关注股票)
public abstract void attach(Observer observer);
// 移除观察者(股民取消关注股票)
public abstract void detach(Observer observer);
// 股票价格上涨,通知所有观察者
public abstract void up();
// 股票价格下跌,通知所有观察者
public abstract void down();
}
3. 具体观察者:Investor.java
/**
* 具体观察者类:股民,实现响应逻辑
*/
public class Investor implements Observer {
@Override
public void buy() {
System.out.println("股票价格上涨5%,股民买股票");
}
@Override
public void cry() {
System.out.println("股票价格下降5%,股民大哭一场");
}
}
4. 具体被观察者:Stock.java
/**
* 具体被观察者类:股票,实现通知逻辑
*/
public class Stock extends Subject {
// 添加观察者(股民关注股票)
@Override
public void attach(Observer observer) {
observers.add(observer);
}
// 移除观察者(股民取消关注股票)
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
// 股票上涨,通知所有观察者执行买股票操作
@Override
public void up() {
for (Object obj : observers) {
((Observer) obj).buy();
}
}
// 股票下跌,通知所有观察者执行大哭操作
@Override
public void down() {
for (Object obs : observers) {
((Observer) obs).cry();
}
}
}
5. 客户端测试类:Client.java
/**
* 测试类:验证股票价格变动通知功能
*/
public class Client {
public static void main(String[] args) {
// 1. 创建观察者(两位股民)
Observer investor1 = new Investor();
Observer investor2 = new Investor();
// 2. 创建被观察者(股票)
Subject stock = new Stock();
// 3. 股民关注股票(添加观察者)
stock.attach(investor1);
stock.attach(investor2);
// 4. 股票价格上涨5%,触发通知
System.out.println("=== 股票价格上涨5% ===");
stock.up();
// 5. 股票价格下跌5%,触发通知
System.out.println("\n=== 股票价格下跌5% ===");
stock.down();
// 6. 测试移除观察者(股民2取消关注)
System.out.println("\n=== 股民2取消关注股票 ===");
stock.detach(investor2);
// 7. 再次触发价格上涨
System.out.println("=== 股票价格再次上涨5% ===");
stock.up();
}
}
四、运行结果
=== 股票价格上涨5% ===
股票价格上涨5%,股民买股票
股票价格上涨5%,股民买股票
=== 股票价格下跌5% ===
股票价格下降5%,股民大哭一场
股票价格下降5%,股民大哭一场
=== 股民2取消关注股票 ===
=== 股票价格再次上涨5% ===
股票价格上涨5%,股民买股票
从运行结果可以看出:
-
两位股民同时关注股票时,价格变动会通知所有观察者
-
股民2取消关注后,仅剩余观察者(股民1)收到通知
-
被观察者与观察者解耦,股票无需知道股民具体身份,仅通过接口通知
五、观察者模式核心优势与特性
1. 核心优势
-
解耦被观察者与观察者:两者通过抽象接口交互,互不依赖具体实现,便于单独扩展
-
动态订阅/取消:支持观察者随时添加/移除,灵活性高(如股民随时关注/取消关注股票)
-
广播通知:被观察者状态变化时,自动通知所有观察者,无需手动调用
-
符合开闭原则:新增观察者时无需修改被观察者代码,仅需实现抽象观察者接口
2. 适用场景与注意事项
适用场景
-
一个对象状态变化需同步更新多个对象(如股票提醒、消息通知、数据监控)
-
需动态维护“订阅-通知”关系(如公众号关注、邮件订阅)
-
希望减少对象间直接耦合,提高系统可维护性
注意事项
-
避免循环依赖:观察者状态变化不应反向触发被观察者状态变化,否则会导致无限循环
-
控制通知顺序:默认按添加顺序通知观察者,若需指定顺序需额外处理
-
性能考虑:观察者过多时,通知可能耗时,可考虑异步通知或分批通知
六、总结
通过本次股票价格提醒的实践案例,深刻体会到观察者模式在“状态同步”场景中的核心价值。它将“被观察者状态变化”与“观察者响应”解耦,让系统结构更清晰、扩展性更强,避免了对象间的直接耦合。
在实际开发中,观察者模式的应用非常广泛:如GUI开发中的按钮点击事件监听、分布式系统中的消息通知、电商平台的订单状态变更通知(用户、商家、物流同步响应)等。合理运用观察者模式,能有效提升系统的灵活性和可维护性。

浙公网安备 33010602011771号