C++观察者模式:高效事件处理指南,设计模式(C++)详解——备忘录模式(1)。
·
观察者模式的核心结构
观察者模式由两个主要角色组成:Subject(主题)和Observer(观察者)。Subject维护一个观察者列表,提供注册和注销观察者的接口,并在状态变化时通知所有观察者。Observer定义一个更新接口,用于接收Subject的通知。
在C++中,可以使用抽象基类或接口定义Observer的通用行为:
class Observer {
public:
virtual ~Observer() = default;
virtual void update(const std::string& message) = 0;
};
Subject类通常包含管理观察者的方法:
class Subject {
private:
std::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(const std::string& message) {
for (auto observer : observers_) {
observer->update(message);
}
}
};
具体实现示例
通过继承Observer接口创建具体观察者类,每个观察者实现自己的update方法以定义对通知的响应方式:
class ConcreteObserver : public Observer {
private:
std::string name_;
public:
explicit ConcreteObserver(const std::string& name) : name_(name) {}
void update(const std::string& message) override {
std::cout << name_ << " received: " << message << std::endl;
}
};
Subject的具体实现可以扩展基本功能:
class ConcreteSubject : public Subject {
private:
std::string state_;
public:
void setState(const std::string& state) {
state_ = state;
notify(state);
}
};
线程安全改进
标准实现存在线程安全问题。通过使用互斥锁保护观察者列表:
#include <mutex>
class ThreadSafeSubject : public Subject {
private:
std::mutex mtx_;
public:
void attach(Observer* observer) override {
std::lock_guard<std::mutex> lock(mtx_);
Subject::attach(observer);
}
void detach(Observer* observer) override {
std::lock_guard<std::mutex> lock(mtx_);
Subject::detach(observer);
}
void notify(const std::string& message) override {
std::lock_guard<std::mutex> lock(mtx_);
Subject::notify(message);
}
};
性能优化策略
为避免在通知期间持有锁时间过长,可以复制观察者列表:
void notify(const std::string& message) override {
std::vector<Observer*> observers_copy;
{
std::lock_guard<std::mutex> lock(mtx_);
observers_copy = observers_;
}
for (auto observer : observers_copy) {
observer->update(message);
}
}
对于高频事件,可采用事件队列机制,将通知放入队列由单独线程处理。
智能指针管理
使用shared_ptr和weak_ptr避免内存管理问题:
class Observer : public std::enable_shared_from_this<Observer> {
public:
virtual ~Observer() = default;
virtual void update(const std::string& message) = 0;
};
class Subject {
private:
std::vector<std::weak_ptr<Observer>> observers_;
public:
void attach(std::shared_ptr<Observer> observer) {
observers_.push_back(observer);
}
void notify(const std::string& message) {
for (auto it = observers_.begin(); it != observers_.end(); ) {
if (auto observer = it->lock()) {
observer->update(message);
++it;
} else {
it = observers_.erase(it);
}
}
}
};
模板化实现
使用模板实现类型安全的观察者模式:
template<typename T>
class Observer {
public:
virtual ~Observer() = default;
virtual void update(const T& data) = 0;
};
template<typename T>
class Subject {
private:
std::vector<Observer<T>*> observers_;
public:
void attach(Observer<T>* observer) {
observers_.push_back(observer);
}
void notify(const T& data) {
for (auto observer : observers_) {
observer->update(data);
}
}
};
实际应用场景
在GUI开发中,按钮控件可作为Subject,各种UI元素作为Observer响应点击事件。游戏开发中,成就系统可以观察玩家状态变化。分布式系统中,服务可用性监控也常采用此模式。
// GUI按钮示例
class Button : public Subject {
public:
void click() {
notify("button clicked");
}
};
class Label : public Observer {
public:
void update(const std::string& message) override {
if (message == "button clicked") {
setText("Button was clicked");
}
}
void setText(const std::string& text) {
// 更新标签文本
}
};
与其他模式结合
观察者模式常与中介者模式结合使用,通过中介者管理复杂的观察关系。在MVC架构中,模型作为Subject,视图作为Observer,实现数据与显示的分离。
// 结合中介者模式
class Mediator {
private:
std::unordered_map<std::string, std::vector<Observer*>> subscriptions_;
public:
void subscribe(const std::string& event, Observer* observer) {
subscriptions_[event].push_back(observer);
}
void publish(const std::string& event, const std::string& message) {
for (auto observer : subscriptions_[event]) {
observer->update(message);
}
}
};
更多推荐
所有评论(0)