贵州百度seo整站优化,珠海医疗网站建设公司,重庆响应式网站建设哪家有,试用网站cms1 观察者模式的概念
观察者模式#xff08;Observer Pattern#xff09;是设计模式中的一种行为模式#xff0c;它定义了一种一对多的依赖关系#xff0c;让多个观察者对象同时监听某一个主题对象。当主题对象状态发生变化时#xff0c;它的所有依赖者#xff08;观察者…1 观察者模式的概念
观察者模式Observer Pattern是设计模式中的一种行为模式它定义了一种一对多的依赖关系让多个观察者对象同时监听某一个主题对象。当主题对象状态发生变化时它的所有依赖者观察者都会收到通知并自动更新。
在 C 中观察者模式通常包含以下几个关键部分
1主题Subject 主题是一个包含观察者列表的抽象类或接口。它提供注册、移除和通知观察者的方法。当主题状态发生变化时它会调用通知方法来更新所有注册的观察者。
2具体主题Concrete Subject 具体主题实现主题的接口通常包含具体的状态或数据。当这些状态或数据发生变化时它会通知观察者。
3观察者Observer 观察者是一个接口或抽象类定义了观察者接收到通知时需要执行的操作。
4具体观察者Concrete Observer 具体观察者实现观察者的接口并在接收到通知时执行具体的操作。
2 观察者模式的实现步骤
在 C 实现观察者模式的实现步骤如下
1定义观察者接口Observer
创建一个观察者接口通常包含一个或多个纯虚函数用于在主题状态发生变化时被调用。
2实现具体观察者ConcreteObserver
创建一个或多个具体观察者类实现观察者接口并定义当接收到通知时需要执行的具体操作。
3定义主题接口Subject
创建一个主题接口包含注册观察者、移除观察者和通知观察者的方法。
4实现具体主题ConcreteSubject
创建一个具体主题类实现主题接口并维护一个观察者列表。提供注册观察者方法允许将观察者添加到观察者列表中。提供移除观察者方法允许从观察者列表中移除特定的观察者。实现通知观察者方法当主题状态发生变化时遍历观察者列表并调用观察者的更新方法。
5在主题中维护观察者列表
具体主题类内部应该有一个容器如std::vector、std::list等来存储所有注册的观察者对象。
6实现通知机制
在具体主题类中当状态发生变化或某些事件发生时调用通知观察者方法。通知方法应该遍历观察者列表并调用每个观察者的更新方法传递必要的信息。
7注册与移除观察者
允许客户端代码在运行时注册新的观察者或移除已注册的观察者。注册操作应将观察者添加到观察者列表中移除操作应从列表中删除指定的观察者。
8客户端使用
在客户端代码中创建具体主题和具体观察者的实例。将具体观察者注册到具体主题中。当具体主题的状态发生变化时它将自动通知所有注册的观察者。
通过以上步骤C 中的观察者模式就实现了。它提供了一种松耦合的方式来处理对象之间的依赖关系使得主题对象可以在不直接依赖具体观察者的情况下通知它们状态的变化。这增强了代码的可维护性和可扩展性。
如下为样例代码
#include iostream
#include vector
#include memory
#include algorithm
#include string // 观察者接口
class Observer {
public:virtual ~Observer() default;virtual void update(const std::string message) 0;
};// 具体观察者
class ConcreteObserver : public Observer {
public:void update(const std::string message) override {std::cout ConcreteObserver received: message std::endl;}
};// 主题接口
class Subject {
public:virtual ~Subject() default;virtual void registerObserver(const std::shared_ptrObserver observer) 0;virtual void removeObserver(const std::shared_ptrObserver observer) 0;virtual void notifyObservers(const std::string message) 0;
};// 具体主题
class ConcreteSubject : public Subject {
public:void registerObserver(const std::shared_ptrObserver observer) override {observers.push_back(observer);}void removeObserver(const std::shared_ptrObserver observer) override {observers.erase(std::remove(observers.begin(), observers.end(), observer),observers.end());}void notifyObservers(const std::string message) override {for (auto observer : observers) {observer-update(message);}}private:std::vectorstd::shared_ptrObserver observers;
};int main()
{// 使用智能指针管理主题和观察者 std::shared_ptrConcreteSubject subject std::make_sharedConcreteSubject();std::shared_ptrObserver observer1 std::make_sharedConcreteObserver();std::shared_ptrObserver observer2 std::make_sharedConcreteObserver();// 注册观察者 subject-registerObserver(observer1);subject-registerObserver(observer2);// 通知观察者 subject-notifyObservers(Hello, Observers!);// 移除一个观察者 subject-removeObserver(observer1);// 再次通知观察者 subject-notifyObservers(Hello again, Observers!);return 0;
}上面代码的输出为
ConcreteObserver received: Hello, Observers!
ConcreteObserver received: Hello, Observers!
ConcreteObserver received: Hello again, Observers!3 观察者模式的应用场景
C 中的观察者模式允许对象之间建立一种一对多的依赖关系使得当一个对象状态发生改变时它的所有依赖者即观察者都会收到通知并自动更新。这种设计模式在多种应用场景中都能发挥重要作用以下是一些具体的应用场景
1图形用户界面GUI开发 当用户与GUI进行交互时如点击按钮或拖动滑块观察者模式可以用于处理这些事件。例如按钮的点击事件可以被注册为观察者的多个组件监听当按钮被点击时所有监听该事件的组件都会收到通知并执行相应的操作。
2实时数据监控 在需要实时监控数据变化的系统中如股票交易系统、环境监测系统等观察者模式可以用于在数据发生变化时通知所有相关的观察者。观察者可以根据接收到的数据更新其状态或执行其他操作。
3游戏开发 在游戏中角色的状态如生命值、位置等可能会频繁变化。通过使用观察者模式游戏引擎可以在角色状态发生变化时通知所有相关的游戏对象如界面元素、AI系统等以便它们能够相应地更新或做出反应。
4消息传递和通知系统 在分布式系统或微服务架构中观察者模式可以用于实现发布/订阅机制。当某个服务发布消息或事件时所有订阅了该消息或事件的观察者都会收到通知并进行处理。
5网络编程 在网络编程中服务器可能会接收到来自客户端的各种请求或消息。通过使用观察者模式服务器可以将这些请求或消息广播给所有相关的处理器或观察者以便它们能够进行相应的处理。
6多线程编程 在多线程环境中线程之间的通信和同步是一个重要问题。观察者模式可以用于实现线程之间的解耦和异步通知。当一个线程的状态或数据发生变化时它可以通知其他线程进行相应的操作而无需直接依赖或同步这些线程。
7配置文件或数据库变化监听 当配置文件或数据库中的数据发生变化时观察者模式可以用于通知相关的应用程序组件进行更新或重新加载配置。
3.1 观察者模式应用于图形用户界面GUI开发
下面是一个简化的示例展示了如何在图形用户界面GUI开发中实现观察者模式。
首先定义观察者接口和具体观察者
#include iostream
#include memory
#include vector
#include algorithm
#include string // 观察者接口
class Observer {
public: virtual ~Observer() default; virtual void update() 0;
}; // 具体观察者 - 处理按钮点击事件的类
class ButtonClickHandler : public Observer {
public: void update() override { std::cout Button was clicked! Handling the event... std::endl; // 执行实际的按钮点击处理逻辑 }
};接下来定义主题接口和具体主题
// 主题接口
class Subject {
public:virtual ~Subject() default;virtual void registerObserver(const std::shared_ptrObserver observer) 0;virtual void removeObserver(const std::shared_ptrObserver observer) 0;virtual void notifyObservers() 0;
};// 具体主题 - 代表一个按钮
class Button : public Subject {
public:void registerObserver(const std::shared_ptrObserver observer) override {observers.push_back(observer);}void removeObserver(const std::shared_ptrObserver observer) override {observers.erase(std::remove(observers.begin(), observers.end(), observer),observers.end());}void notifyObservers() override {for (const auto observer : observers) {observer-update();}}// 假设这是按钮被点击时调用的方法 void onClick() {std::cout Button clicked. Notifying observers... std::endl;notifyObservers();}private:std::vectorstd::shared_ptrObserver observers;
};最后在主函数中使用这些类来模拟 GUI 中的按钮点击事件处理
int main()
{// 创建具体观察者按钮点击处理器 std::shared_ptrObserver buttonClickHandler std::make_sharedButtonClickHandler();// 创建具体主题按钮 std::shared_ptrSubject button std::make_sharedButton();// 将按钮转换为Button类型以便注册观察者 std::shared_ptrButton buttonPtr std::static_pointer_castButton(button);// 注册观察者到主题将按钮点击处理器注册到按钮 buttonPtr-registerObserver(buttonClickHandler);// 模拟按钮被点击的事件 buttonPtr-onClick();// 移除观察者如果需要的话 // buttonPtr-removeObserver(buttonClickHandler); return 0;
}上面代码的输出为
Button clicked. Notifying observers...
Button was clicked! Handling the event...上面代码使用了 std::shared_ptr 来管理观察者和主题的生命周期。当 std::shared_ptr 的引用计数变为0时对应的对象会被自动删除。但是请注意这种方法可能会导致循环引用问题如果主题和观察者相互持有对方的 std::shared_ptr则它们将永远不会被删除。为了避免这种情况通常建议仅在必要时使用 std::shared_ptr并在可能的情况下使用原始指针、裸指针或 std::weak_ptr。
3.2 观察者模式应用于实时数据监控
以下是一个使用观察者模式实现实时数据监控的示例
首先定义观察者接口和主题接口
#include iostream
#include memory
#include vector
#include mutex // 观察者接口
class Observer {
public: virtual ~Observer() default; virtual void update(const double data) 0;
}; // 主题接口
class Subject {
public: virtual ~Subject() default; virtual void attach(const std::shared_ptrObserver observer) 0; virtual void detach(const std::shared_ptrObserver observer) 0; virtual void notify(const double data) 0;
};接着实现具体的观察者和主题类
// 具体观察者类
class RealtimeDataObserver : public Observer {
public:void update(const double data) override {std::cout Observer received new data: data std::endl;// 处理实时数据的逻辑 }
};// 具体主题类
class RealtimeDataSubject : public Subject {
public:void attach(const std::shared_ptrObserver observer) override {std::lock_guardstd::mutex lock(mtx);observers.push_back(observer);}void detach(const std::shared_ptrObserver observer) override {std::lock_guardstd::mutex lock(mtx);observers.erase(std::remove(observers.begin(), observers.end(), observer),observers.end());}void notify(const double data) override {std::lock_guardstd::mutex lock(mtx);for (const auto observer : observers) {observer-update(data);}}private:std::vectorstd::shared_ptrObserver observers;mutable std::mutex mtx;
};在上面的代码中RealtimeDataSubject 维护了一个观察者列表并在数据更新时调用所有观察者的 update 方法。使用 std::mutex 确保在多线程环境中对观察者列表的修改是线程安全的。
最后在主函数中使用这些类来模拟实时数据监控
int main()
{// 创建主题对象 std::shared_ptrSubject subject std::make_sharedRealtimeDataSubject();// 创建观察者对象 std::shared_ptrObserver observer1 std::make_sharedRealtimeDataObserver();std::shared_ptrObserver observer2 std::make_sharedRealtimeDataObserver();// 将观察者附加到主题上 subject-attach(observer1);subject-attach(observer2);// 模拟实时数据更新 for (int i 0; i 5; i) {double newData static_castdouble(i); // 假设的实时数据 subject-notify(newData);// 可以在这里添加一些延迟以模拟实时数据更新的间隔 }// 移除某个观察者如果需要 // subject-detach(observer1); return 0;
}上面代码的输出为
Observer received new data: 0
Observer received new data: 0
Observer received new data: 1
Observer received new data: 1
Observer received new data: 2
Observer received new data: 2
Observer received new data: 3
Observer received new data: 3
Observer received new data: 4
Observer received new data: 4在这个例子中创建了一个 RealtimeDataSubjec t对象和两个 RealtimeDataObserver 对象。当实时数据更新时通过调用 notify 方法来通知所有观察者。此外由于实时数据监控可能涉及多线程所以使用了 std::mutex 来确保线程安全。在实际应用中还应该考虑更复杂的并发控制策略比如使用读写锁std::shared_mutex来优化性能如果读操作远多于写操作的话。
4 观察者模式的优点与缺点
C 观察者模式的优点主要包括
1解耦 观察者模式降低了主题和观察者之间的耦合度。主题和观察者可以独立地改变和复用只要他们遵守观察者模式的接口就能无缝地集成在一起。
2灵活性 可以动态地增加和删除观察者。这使得程序能够在运行时根据需求调整通知机制。
3支持广播通信 主题可以通知多个观察者无需知道它们的具体数量或类型。这使得实现一对多的通信变得非常简单。
4遵循开闭原则 对扩展开放对修改封闭。可以添加新的观察者类而无需修改已有的主题类或观察者类。
然而C 观察者模式也存在一些缺点
1性能问题 如果观察者数量非常多或者通知操作非常耗时那么每次主题状态变化时都可能导致大量的通知操作从而影响性能。
2依赖管理 如果观察者之间也存在依赖关系那么可能会导致复杂的依赖网络使得代码难以理解和维护。
3内存泄漏风险 如果使用 std::shared_ptr 而没有正确管理生命周期可能会导致循环引用和内存泄漏。尽管可以通过 std::weak_ptr 来避免循环引用但这会增加实现的复杂性。
4可能导致过度通知 在某些情况下可能不需要每次主题状态变化都通知所有观察者。过度的通知可能会浪费计算资源并可能导致不必要的副作用。
5接口标准化 观察者模式要求主题和观察者之间通过统一的接口进行通信。这可能导致接口过于复杂或不够灵活以适应所有可能的观察者和主题类型。