定义了一对多的依赖关系,让多个观察者对象同时监听某一主体对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
#include <algorithm>
#include <iostream>
#include <memory>
#include <vector>
class ConcreteSubject;
/* 抽象观察者,为所有具体观察者定义一个接口,在得到主题通知时更新自己 */
class Observer {
public:
explicit Observer(const std::shared_ptr<ConcreteSubject> &subject)
: subject_(subject) {}
virtual void update() = 0;
virtual ~Observer() = default;
protected:
std::weak_ptr<ConcreteSubject> subject_;
};
/* 主题/抽象通知者 */
class Subject {
public:
/* 增加观察者 */
void attach(const std::shared_ptr<Observer> &observer) {
observers.emplace_back(observer);
}
/* 移除观察者 */
void detach(const std::shared_ptr<Observer> &observer) {
observers.erase(std::remove(observers.begin(), observers.end(), observer));
}
/* 通知 */
void notify() {
for (auto &ob : observers) {
ob->update();
}
}
virtual ~Subject() = default;
private:
std::vector<std::shared_ptr<Observer>> observers;
};
/* 具体主题/具体通知者 */
class ConcreteSubject final : public Subject {
public:
std::string getState() const { return subjectState; }
void setState(const std::string &value) { subjectState = value; }
~ConcreteSubject() = default;
private:
std::string subjectState;
};
class ConcreteObserver final : public Observer {
public:
ConcreteObserver(const std::shared_ptr<ConcreteSubject> &subject,
const std::string name)
: Observer(subject), name_(name) {}
void update() override {
if (const auto p = subject_.lock()) {
observerState_ = p->getState();
std::cout << "Observer" << name_ << " new state is " << observerState_
<< '\n';
}
}
private:
std::string name_;
std::string observerState_;
};
auto main() -> int {
std::shared_ptr<ConcreteSubject> subject =
std::make_shared<ConcreteSubject>();
std::shared_ptr<ConcreteObserver> ob1 =
std::make_shared<ConcreteObserver>(subject, "X");
std::shared_ptr<ConcreteObserver> ob2 =
std::make_shared<ConcreteObserver>(subject, "Y");
std::shared_ptr<ConcreteObserver> ob3 =
std::make_shared<ConcreteObserver>(subject, "Z");
subject->attach(ob1);
subject->attach(ob2);
subject->attach(ob3);
subject->setState("ABC");
subject->notify();
std::cout << '\n';
subject->detach(ob1);
subject->setState("DEF");
subject->notify();
return 0;
}
将一个系统分割成一系列相互协作的类需要维护相关对象间的一致性。这样的耦合性会给维护、扩展和重用带来不便。
观察者模式实际上就是在解耦,让耦合的双方都依赖于抽象,而不依赖于具体。