观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖着都会收到通知并自动更新。
当两个对象之间松耦合,他们依然可以交互,但是不太清楚彼此的细节。观察者模式提供了一种对象设计,让主题和观察者之间松耦合。我们可以独立复用主题和观察者,如果我们在其他地方需要使用主题或观察者,可以轻易地复用,因为二者并非紧耦合。改变主题或者观察者其中一方,并不会影响另一方。因为两者是松耦合的,所以只要他们之间的接口仍被遵守,我们就可以自由地改变他们。
松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低。
书上的例子是一个天气公告牌,代码如下:
Weather.h
#include#include class Observer {public: virtual void update(float temp) = 0;};class DisplayElement {public: virtual void display() = 0;};class Subject {public: virtual void registerObserver(Observer& o) = 0; virtual void removeObserver(Observer& o) = 0; virtual void notifyObservers() = 0;};class WeatherDate : public Subject {public: ~WeatherDate(); void registerObserver(Observer& o); void removeObserver(Observer& o); void notifyObservers(); void measurementsChanged(); void setMeasurements(float temp);private: std::vector observerList; float temperature = 0;};class WeatherBoard01: public Observer, DisplayElement {public: WeatherBoard01(Subject& weatherDate, std::string name); ~WeatherBoard01(); void update(float temp); void display();private: std::string name = ""; float temperature = 0; Subject* weatherDate = nullptr;};void weatherTest();
Weather.cpp
#include#include "Weather.h"WeatherDate::~WeatherDate() { for (auto it: observerList) { delete it; }}void WeatherDate::registerObserver(Observer &o) { observerList.push_back(&o);}void WeatherDate::removeObserver(Observer &o) { for (auto it = observerList.begin(); it != observerList.end(); it++) { if (*it == &o) { observerList.erase(it); break; } }}void WeatherDate::notifyObservers() { for (auto it: observerList) { it->update(temperature); }}void WeatherDate::measurementsChanged() { notifyObservers();}void WeatherDate::setMeasurements(float temp) { temperature = temp; measurementsChanged();}WeatherBoard01::WeatherBoard01(Subject &weatherDate, std::string name) { this->weatherDate = &weatherDate; this->name = name; weatherDate.registerObserver(*this); weatherDate.notifyObservers();}WeatherBoard01::~WeatherBoard01() { delete weatherDate;}void WeatherBoard01::update(float temp) { temperature = temp; display();}void WeatherBoard01::display() { std::cout<<"WeatherBoard01("< <<"): "< <
需要注意的东西大概:
1. 如果类成员变量是指针vector,应该如何析构?
2. 抽象类不能直接作为函数的参数。那么是传引用更好还是传指针更好?
3. vector的方法待学习。
blog的观察者模式实现了一个博客和订阅者的关系,具体见:https://blog.csdn.net/wuzhekai1985/article/details/6674984
两者区别在于:
1. blog里的代码没有具体实现析构函数。但是对于有指针成员的类,应该手动delete。所以还是不知道指针vector怎么析构。
2. 一个好的思路:观察者对主题的指针也可以设计成指针vector,这样的话就允许一个观察者同时观察多个主题,把一对多的关系扩展为多对多的关系。