C++观察者模式与信号槽实现
请用C++实现观察者模式(Observer Pattern),包括主题(Subject)和观察者(Observer)接口、事件通知机制,并对比使用std::function的现代实现与经典虚函数实现。
回答
孤独的心
经典实现(基于虚函数):
class Observer {
public:
virtual ~Observer() = default;
virtual void update(const Event&) = 0;
};
class Subject {
std::vector<std::weak_ptr<Observer>> observers;
public:
void attach(std::shared_ptr<Observer> obs) {
observers.push_back(obs);
}
void notify(const Event& e) {
for (auto& wobs : observers) {
if (auto obs = wobs.lock()) obs->update(e);
}
// 清理已销毁的观察者
std::erase_if(observers, [](auto& w) { return w.expired(); });
}
};
现代C++实现(基于std::function,更灵活,无需定义Observer接口):
class EventBus {
std::unordered_map<EventType, std::vector<std::function<void(const Event&)>>> handlers;
std::mutex mtx;
public:
template<typename F>
void subscribe(EventType t, F&& f) {
std::lock_guard lk(mtx);
handlers[t].emplace_back(std::forward<F>(f));
}
void publish(EventType t, const Event& e) {
std::lock_guard lk(mtx);
if (auto it = handlers.find(t); it != handlers.end())
for (auto& h : it->second) h(e);
}
};
选择建议:
- 虚函数方法适合强类型、接口固定的场景。
- std::function方法适合灵活、Lambda驱动的现代C++风格。
- 线程安全需注意(加锁或使用单线程事件循环)。
- 注意观察者生命周期管理(weak_ptr或令牌式订阅返回可取消订阅的句柄)。