C++观察者模式代码实例

C++观察者模式代码实例一

下面是一个简单的C++观察者模式的实现示例,这里仅给出核心代码框架,完整的工程应包含对应的头文件声明及必要的#include指令等。

// 观察者接口(Observer)
class IObserver {
public:
    virtual ~IObserver() {}
    virtual void update(const std::string& message) = 0; // 更新方法
};

// 主题接口(Subject)
class ISubject {
public:
    virtual ~ISubject() {}
    virtual void registerObserver(IObserver* observer) = 0; // 注册观察者
    virtual void removeObserver(IObserver* observer) = 0; // 移除观察者
    virtual void notifyObservers(const std::string& message) = 0; // 通知观察者
};

// 具体主题(ConcreteSubject)
class ConcreteSubject : public ISubject {
private:
    std::vector<IObserver*> observers; // 存储观察者列表

public:
    void registerObserver(IObserver* observer) override {
        observers.push_back(observer);
    }

    void removeObserver(IObserver* observer) override {
        observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
    }

    void notifyObservers(const std::string& message) override {
        for (const auto& obs : observers) {
            obs->update(message);
        }
    }

    // 其他业务逻辑,当有状态改变时调用notifyObservers()
    void changeState(const std::string& newState) {
        // 假设这里有某种状态变更逻辑
        std::string message = "状态已更新至:" + newState;
        notifyObservers(message);
    }
};

// 具体观察者(ConcreteObserver)
class ConcreteObserver : public IObserver {
public:
    void update(const std::string& message) override {
        std::cout << "Observer received message: " << message << std::endl;
        // 在此处响应状态变更,执行观察者的相关操作
    }
};

// 使用示例
int main() {
    ConcreteSubject subject;
    ConcreteObserver observer1;
    ConcreteObserver observer2;

    subject.registerObserver(&observer1);
    subject.registerObserver(&observer2);

    subject.changeState("New State"); // 当状态变化时,所有观察者都会被通知

    return 0;
}

在这个例子中,ConcreteSubject 是具体的主题类,它可以添加和移除观察者,并在状态变化时通过调用 notifyObservers() 方法通知所有的观察者。ConcreteObserver 类则是实现了 IObserver 接口的观察者,当收到 update() 调用时,会执行相应的更新操作。主程序中创建了一个主题实例和两个观察者实例,并将观察者注册到主题上,当主题状态发生变化时,观察者接收到通知并作出反应。

在实际应用中,观察者模式通常用于设计事件驱动的系统,或者是当对象的状态变化需要自动通知其他对象时。以下是对上述代码实例的进一步阐述:

  1. 应用场景举例:假设你正在构建一个气象站系统,其中ConcreteSubject代表气象站,它记录并报告实时天气数据。ConcreteObserver可以代表各种订阅气象信息的实体,如天气预报网站、农业自动化系统、交通管理系统等。

  2. 主体(Subject):当气象站检测到天气数据发生改变时,例如温度、湿度或风速变化,它会调用notifyObservers()方法,通知所有已注册的观察者。

  3. 观察者(Observer):每一个观察者在接收到update()调用时,会按照自己的需求处理这个更新消息。比如,天气预报网站会在页面上实时更新数据,农业自动化系统会据此调整灌溉计划,交通管理系统则可能据此发布道路预警信息。

  4. 灵活性:观察者模式提供了很好的灵活性,因为新增加的观察者只需实现IObserver接口,并通过主题的registerObserver()方法注册自己,就可以开始接收更新通知,而不需要修改原有的主体或其它观察者。

  5. 松耦合:通过观察者模式,主题与观察者之间的耦合度较低,两者之间通过接口进行交互,这有助于简化系统的维护和扩展。

总之,通过这个简单的C++观察者模式实例,我们可以了解到如何构建一个具有动态通知机制的系统,使得当对象状态改变时,它的所有依赖对象都能得到及时的更新。在实际开发中,观察者模式广泛应用于GUI编程、事件处理、游戏开发、分布式系统等多种场景。

C++观察者模式代码实例二

另外,观察者模式还可以结合C++的一些现代特性进行优化,例如使用智能指针来管理观察者生命周期,以避免内存泄漏问题。下面是一个使用std::shared_ptr改进后的观察者列表管理的例子:

#include <iostream>
#include <vector>
#include <memory>

// 观察者接口(Observer)
class IObserver {
public:
    virtual ~IObserver() {}
    virtual void update(const std::string& message) = 0;
};

// 主题接口(Subject)
class ISubject {
public:
    virtual ~ISubject() {}
    virtual void attach(std::shared_ptr<IObserver> observer) = 0;
    virtual void detach(std::shared_ptr<IObserver> observer) = 0;
    virtual void notifyObservers(const std::string& message) = 0;
};

// 具体主题(ConcreteSubject)
class ConcreteSubject : public ISubject {
private:
    std::vector<std::shared_ptr<IObserver>> observers;

public:
    void attach(std::shared_ptr<IObserver> observer) override {
        observers.push_back(observer);
    }

    void detach(std::shared_ptr<IObserver> observer) override {
        observers.erase(
            std::remove(observers.begin(), observers.end(), observer),
            observers.end()
        );
    }

    void notifyObservers(const std::string& message) override {
        for (const auto& obs : observers) {
            obs->update(message);
        }
    }

    // 其他业务逻辑...
};

// 具体观察者(ConcreteObserver)
class ConcreteObserver : public IObserver {
public:
    void update(const std::string& message) override {
        std::cout << "Observer received message: " << message << std::endl;
        // 在此处响应状态变更,执行观察者的相关操作
    }
};

// 使用示例
int main() {
    ConcreteSubject subject;
    auto observer1 = std::make_shared<ConcreteObserver>();
    auto observer2 = std::make_shared<ConcreteObserver>();

    subject.attach(observer1);
    subject.attach(observer2);

    subject.notifyObservers("New State"); // 当状态变化时,所有观察者都会被通知

    return 0;
}

在这个改进版中,观察者列表现在存储的是指向观察者的智能指针,这样当观察者不再需要时,可以自动释放其占用的内存,有效防止了内存泄漏。同时,这也使得主题类与观察者之间的关系管理更加安全和可靠。

此外,观察者模式还可以与C++11/14/17的新特性结合起来,以更好地适应现代C++编程实践。例如:

  1. Lambda 表达式:在某些情况下,你可以使用lambda表达式作为临时观察者,这样就不必为一次性任务专门创建一个类。例如:
subject.attach([&](const std::string& message) {
    std::cout << "Anonymous observer received message: " << message << std::endl;
});

subject.notifyObservers("New State");
  1. std::functionstd::bind:如果你需要传递已经存在的函数或成员函数作为观察者,可以使用std::functionstd::bind来包装这些函数。例如,假设你有一个打印日志的全局函数或类成员函数:
void logMessage(const std::string& message) {
    std::cout << "Log system received message: " << message << std::endl;
}

// 全局函数
subject.attach(logMessage);

// 成员函数,假设有一个Logger类
class Logger {
public:
    void log(const std::string& message) {
        std::cout << "Logger received message: " << message << std::endl;
    }
};

Logger logger;
subject.attach(std::bind(&Logger::log, &logger, std::placeholders::_1));

通过这些现代C++特性的应用,观察者模式变得更加灵活,可以适应更多样化的场景和需求。同时,结合智能指针和其他内存管理工具,观察者模式的实现可以变得更安全、更易于维护。

除此之外,观察者模式还可以与C++17中的std::variantstd::visit配合使用,以处理不同类型的通知消息。例如,当主题拥有多种状态需要向观察者发送时,可以定义一个包含所有可能状态类型的std::variant变量:

#include <variant>

enum class WeatherDataType { Temperature, Humidity, WindSpeed };

struct WeatherData {
    WeatherDataType type;
    double value;
};

class ConcreteSubject : public ISubject {
    // ...
    void notifyObservers(WeatherData data) override {
        for (const auto& obs : observers) {
            obs->update(data);
        }
    }
};

class AdvancedObserver : public IObserver {
public:
    void update(const WeatherData& data) override {
        std::visit(overloaded{
            [&](const auto& value) {
                if (data.type == WeatherDataType::Temperature)
                    handleTemperature(value);
                // 处理其他类型...
            },
        }, data.value);
    }

private:
    void handleTemperature(double temp) {
        std::cout << "Received temperature update: " << temp << std::endl;
    }

    // 处理其他数据类型的方法...
};

在此案例中,WeatherData结构体包含了数据类型和对应的值,观察者可以根据type字段判断所接收数据的具体类型,并通过std::visit调用相应的方法进行处理。

综上所述,观察者模式与现代C++特性相结合,可以构建出更加灵活、类型安全且易于维护的系统,适用于各种复杂的事件驱动和状态变更通知场景。

python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)

50个开发必备的Python经典脚本(11-20)

50个开发必备的Python经典脚本(21-30)

50个开发必备的Python经典脚本(31-40)

50个开发必备的Python经典脚本(41-50)
————————————————

​最后我们放松一下眼睛
在这里插入图片描述

  • 13
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个简单的 C++ 观察者模式实现的代码示例: ``` #include <iostream> #include <vector> using namespace std; class Observer { public: virtual void update() = 0; }; class Subject { private: vector<Observer*> observers; public: void attach(Observer* observer) { observers.push_back(observer); } void detach(Observer* observer) { observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end()); } void notify() { for (Observer* observer : observers) { observer->update(); } } }; class ConcreteObserver1 : public Observer { public: void update() { cout << "ConcreteObserver1 received the update." << endl; } }; class ConcreteObserver2 : public Observer { public: void update() { cout << "ConcreteObserver2 received the update." << endl; } }; class ConcreteSubject : public Subject { public: void doSomething() { cout << "ConcreteSubject is doing something." << endl; notify(); } }; int main() { ConcreteSubject subject; ConcreteObserver1 observer1; ConcreteObserver2 observer2; subject.attach(&observer1); subject.attach(&observer2); subject.doSomething(); subject.detach(&observer2); subject.doSomething(); return 0; } ``` 在这个实现中,我们定义了一个 Observer 接口和一个 Subject 类。具体的观察者 ConcreteObserver1 和 ConcreteObserver2 实现了 Observer 接口,而具体的被观察者 ConcreteSubject 继承了 Subject 类。 ConcreteSubject 类中有一个 doSomething() 方法,它会触发 notify() 方法,通知所有注册过的观察者。被观察者可以通过 attach() 方法注册观察者,detach() 方法注销观察者。 在 main() 函数中,我们创建了 ConcreteSubject 和两个 ConcreteObserver 的实例,注册了这两个观察者,然后调用 doSomething() 方法触发通知。我们还演示了如何注销一个观察者,然后再次触发通知。 这个简单的实现可以帮助你理解观察者模式的基本原理和实现方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极致人生-010

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值