观察者模式(Observer)
当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.
理解
如同在动物园看动物,当动物的行为、状态发生改变时,所有的游客(观察者)都自动收到信息.常用于通知类型的设计.
优点
观察者和被观察者是抽象耦合的,依赖关系被弱化.
缺点
在规模庞大时,让所有观察者接收到更新通知将会花费很长的时间.
实现
在用户使用软件,软件公司发布了软件的一个新版本,这时所有订阅(使用)了软件的用户都得到更新通知.也就是说,观察者(用户)是稳定的,软件版本是变化的.
失败的设计
#include <iostream>
using namespace std;
class User {
public:
double getVersion() { return m_version; }
protected:
double m_version;
};
class Upgrade : public User {
public:
Upgrade(double version) { m_version = version; }
void update() { m_version += 0.01; }//升级的更新操作
};
class Downgrade : public User {
public:
Downgrade(double version) { m_version = version; }
void update() { m_version -= 0.1; }//降级的更新操作
};
int main(void) {
Upgrade user1(2.1);
Downgrade user2(2.2);
user1.update();
user2.update();
//打印各观察者的版本号
cout << user1.getVersion() << endl;
cout << user2.getVersion() << endl;
system("pause");
return 0;
}
需要各个用户分别调用更新函数,如果未更新则无法接收到通知.
成功的设计
#include <iostream>
#include <vector>
using namespace std;
class Observer {
public:
virtual void update() = 0;
void printVersion() { cout << m_version << endl; }
virtual ~Observer(){}
protected:
double m_version;
};
class Upgrade : public Observer {
public:
Upgrade(double version) { m_version = version; }
void update() { m_version += 0.01; }//升级的更新操作
};
class Downgrade : public Observer {
public:
Downgrade(double version) { m_version = version; }
void update() { m_version -= 0.1; }//降级(回滚)的更新操作
};
class User {
public:
//添加、删除观察者
void addObserver(Observer* newObserver) { m_observer.push_back(newObserver); }
void removeObserver() { m_observer.pop_back(); }
void notify() {
for (vector<Observer*>::iterator i = m_observer.begin(); i != m_observer.end(); i++) {
(*i)->update();//多态更新,各司其职
}
}
void printVersion() {//打印各观察者的版本号
for (vector<Observer*>::iterator i = m_observer.begin(); i != m_observer.end(); i++) {
(*i)->printVersion();
}
}
private:
vector<Observer*> m_observer;
};
int main(void) {
User user;
user.addObserver(new Upgrade(2.1));
user.addObserver(new Downgrade(2.2));
user.notify();//更新通知
user.printVersion();
system("pause");
return 0;
}
所有观察者自动更新,不必一个个进行手动操作.