核心思想
观察者模式是一种行为型设计模式,定义了对象之间的一对多依赖关系。当一个对象(称为Subject,主题)的状态发生改变时,所有依赖于它的对象(称为Observer,观察者)都会自动收到通知并更新。
**Subject:**维护观察者列表,提供注册、移除观察者的方法,以及通知观察者的功能。
**Observer:**定义一个更新接口,用于在Subject状态改变时接收通知。
观察者模式的核心是解耦:Subject和Observer之间没有直接依赖,Subject只需通知Observer,而不需要知道Observer的具体实现。
使用场景
事件驱动系统:如GUI框架中,按钮点击事件通知多个监听器。
发布-订阅模型:如消息队列、事件总线。
数据与UI同步:如MVC架构中,Model变化时自动更新View。
监控系统:如系统状态变化时通知多个监控服务。
游戏开发:如角色状态变化时通知多个UI组件或AI系统。
解决的问题
紧耦合问题:
在传统设计中,Subject需要直接调用Observer的方法,导致两者紧耦合。观察者模式通过引入Observer接口,使Subject和Observer解耦。
动态更新问题:
当Subject状态变化时,需要手动调用所有依赖对象的更新方法。观察者模式通过notify方法自动通知所有Observer。
可扩展性问题:
新增Observer时,需要修改Subject的代码。观察者模式允许动态注册和移除Observer,无需修改Subject。
示例代码
#include <iostream>
#include <list>
#include <memory>
#include <mutex>
// 观察者接口
class Observer {
public:
virtual ~Observer() = default;
virtual void update(const std::string& message) = 0;
};
// 主题基类
class Subject {
protected:
std::list<std::weak_ptr<Observer>> observers; // 使用weak_ptr防止循环引用
std::mutex mutex;//多线程环境下需要使用
public:
// 添加观察者(使用智能指针管理)
void attach(const std::shared_ptr<Observer> observer)
{
std::lock_guard<std::mutex> lock(mutex);
observers.push_back(observer);
}
// 移除观察者
void detach(const std::shared_ptr<Observer> observer)
{
std::lock_guard<std::mutex> lock(mutex);
auto it = observers.begin();
while(it != observers.end())
{//std::weak_ptr的lock()方法返回对应的std::shared_ptr
if(observer == it->lock())
{
it = observers.erase(it);
continue;
}
it++;
}
}
// 通知所有观察者
void notify(const std::string& message)
{
std::lock_guard<std::mutex> lock(mutex);
auto it = observers.begin();
while (it != observers.end())
{//检查观察者是否有效,因为观察者有可能在别的地方被清理了
if (!it->expired())
{//std::weak_ptr的lock()方法返回对应的std::shared_ptr,只能通过std::shared_ptr操作管理的对象
it->lock()->update(message);
++it;
}
else
{
it = observers.erase(it); // 自动清理失效的观察者
}
}
}
};
// 具体主题:新闻发布器
class NewsPublisher : public Subject {
public:
void publishNews(const std::string& news)
{
std::cout << "publishNews: " << news << std::endl;
notify(news); // 通知所有观察者
}
};
// 具体观察者1:邮件订阅者
class EmailSubscriber : public Observer
{
public:
~EmailSubscriber()
{
std::cout << "EmailSubscriber destroyed"<< std::endl;
}
void update(const std::string& message) override
{
std::cout << "EmailSubscriber recive: " << message << std::endl;
}
};
// 具体观察者2:短信订阅者
class SMSSubscriber : public Observer
{
public:
~SMSSubscriber()
{
std::cout << "SMSSubscriber destroyed"<< std::endl;
}
void update(const std::string& message) override
{
std::cout << "SMSSubscriber recive: " << message << std::endl;
}
};
int main() {
// 创建主题
NewsPublisher publisher;
// 创建观察者(使用智能指针)
auto emailSubscriber = std::make_shared<EmailSubscriber>();
auto smsSubscriber = std::make_shared<SMSSubscriber>();
// 注册观察者
publisher.attach(emailSubscriber);
publisher.attach(smsSubscriber);
// 发布新闻(通知所有观察者)
publisher.publishNews("C++20 has been published!");
// 移除一个观察者
publisher.detach(smsSubscriber);
publisher.publishNews("designe patten meeting");
// 测试观察者自动清理
{
auto tempSubscriber = std::make_shared<EmailSubscriber>();
publisher.attach(tempSubscriber);
publisher.publishNews("temporary news");
} // tempSubscriber离开作用域,自动解除注册
publisher.publishNews("only subscriber recived this message.");
return 0;
}
运行输出
publishNews: C++20 has been published!
EmailSubscriber recive: C++20 has been published!
SMSSubscriber recive: C++20 has been published!
publishNews: designe patten meeting
EmailSubscriber recive: designe patten meeting
publishNews: temporary news
EmailSubscriber recive: temporary news
EmailSubscriber recive: temporary news
EmailSubscriber destroyed
publishNews: only subscriber recived this message.
EmailSubscriber recive: only subscriber recived this message.
SMSSubscriber destroyed
EmailSubscriber destroyed