C++——Observer设计模式(侯捷面向高级对象编程)

讲解:侯捷面向对象高级编程——观察者模式(Observer Pattern)

课中Observer框架图

Observer(观察者)模式是一种行为型设计模式,定义了对象之间的一对多依赖关系。当一个对象的状态发生变化时,所有依赖于它的对象都会收到通知并自动更新。这种模式广泛用于实现事件处理系统、数据驱动更新以及 MVC 模式中的视图更新。

主要结构:

  1. Subject(被观察者/主题):

    • 负责维护观察者列表。
    • 提供方法用于注册、移除观察者。
    • 当自身状态发生改变时,通知所有观察者。
  2. Observer(观察者):

    • 定义了一个接口,包含 update() 方法,观察者通过实现该方法来接收通知。
    • 当被观察者的状态变化时,被通知更新。
  3. ConcreteSubject(具体主题):

  • 实现具体的状态变化逻辑。
  • 继承自 Subject 并扩展具体的功能。
  1. ConcreteObserver(具体观察者):
  • 继承自 Observer,实现更新逻辑。
  • 它们会根据 Subject 的通知来更新自己。

UML 图:

Subject
- m_value : int
- m_views : Observer[]
+attach(Observer* obs)
+detach(Observer* obs)
+notify()
«interface»
Observer
+update(Subject* sub, int value)
ConcreteSubject
+set_val(int value)
+get_val()
ConcreteObserver
- m_name : string
+update(Subject* sub, int value)

补充:符号的意义

  • 通过 o-- 语法,表示委托(composition 或 association) 关系

  • 继承关系用 <|-- 来绘制

  • + (Public / 公有)

    • 表示该属性或方法是公有的,即可以被所有对象访问。无论是同一个类、子类,还是类外部的对象,都可以访问公有成员。
  • - (Private / 私有)

    • 表示该属性或方法是私有的,只能在类的内部访问,外部类或子类都无法直接访问。
  • # (Protected / 受保护)

    • 表示该属性或方法是受保护的,只能在类内部或其子类中访问,外部类无法访问。
  • ~ (Package / 默认访问)

    • 表示包级别的访问控制(在 C++ 中相当于“友元”或 Java 的 package-private)。只有在相同包中的类可以访问该成员,包外的类无法访问。

观察者模式的实现步骤:

  1. 定义 Subject 类:负责维护观察者的注册和通知方法。
  2. 定义 Observer 接口:声明 update() 方法,所有观察者类必须实现这个接口。
  3. 定义 ConcreteSubject 和 ConcreteObserver
    • ConcreteSubject 持有状态,当状态改变时调用 notify() 通知观察者。
    • ConcreteObserver 实现 update() 方法以接收被观察者的通知。

使用场景:

  1. GUI 系统:当用户进行操作时,需要更新多个视图,比如按钮点击更新多个面板。
  2. 事件驱动系统:事件发生时,多个处理模块需要对事件进行响应。
  3. 模型-视图-控制器 (MVC):视图(观察者)需要监听模型(被观察者)的变化。

代码示例:

#include <iostream>
#include <vector>
using namespace std;

// 前向声明
class Subject;

// 观察者接口类
class Observer {
public:
    virtual void update(Subject* sub, int value) = 0; // 纯虚函数,强制继承类实现该方法
};

// 被观察者类
class Subject {
    int m_value;  // 被观察者状态
    vector<Observer*> m_views;  // 观察者列表
public:
    // 注册观察者
    void attach(Observer* obs) {
        m_views.push_back(obs);
    }

    // 修改状态并通知观察者
    void set_val(int value) {
        m_value = value;
        notify();
    }

    // 通知所有观察者状态变化
    void notify() {
        for (int i = 0; i < m_views.size(); ++i) {
            m_views[i]->update(this, m_value);  // 调用每个观察者的 update 方法
        }
    }

    int get_val() const {
        return m_value;
    }
};

// 具体的观察者实现类
class ConcreteObserver : public Observer {
    string m_name;  // 观察者名称,用于标识
public:
    ConcreteObserver(const string& name) : m_name(name) {}

    // 实现 update 方法
    void update(Subject* sub, int value) override {
        cout << "Observer " << m_name << " has been notified. New value: " << value << endl;
    }
};

int main() {
    Subject subject;  // 创建被观察者对象

    // 创建观察者对象
    ConcreteObserver observer1("Observer1");
    ConcreteObserver observer2("Observer2");

    // 注册观察者
    subject.attach(&observer1);
    subject.attach(&observer2);

    // 改变被观察者状态并通知观察者
    subject.set_val(10);
    subject.set_val(20);

    return 0;
}

在这个例子中,Subject 持有观察者的列表,当状态 m_value 变化时,所有观察者都会通过 update 方法得到通知。

输出结果

Observer Observer1 has been notified. New value: 10
Observer Observer2 has been notified. New value: 10
Observer Observer1 has been notified. New value: 20
Observer Observer2 has been notified. New value: 20

总结适用场景:

  • 事件驱动系统:比如 GUI 系统中,按钮点击事件通知多个监听器。
  • 数据变化的多视图更新:如 MVC 模式中,模型变化时,通知视图更新。
  • 分布式系统中的状态同步:多个模块依赖某一模块的状态变化。

Observer 模式非常适合那些需要状态变化通知机制的场景,它提供了一种优雅的方式来管理对象之间的依赖关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值