设计模式---观察者模式
背景故事:
老板回来,我不知道!
概念:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。它还有两个别名,依赖(Dependents),发布-订阅(Publish-Subsrcibe)。
大话设计模式中程杰老师对观察者模式的定义是,观察者模式:定义对象间的一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生改变时,会通知所有观察者对象,使它们能够自动更新自己。
结构图:
代码实例:
#include <iostream> #include <vector> #include <string> using namespace std; class Secretary; // 看股票的同事类(观察对象,观察者) class StockObserver { public: StockObserver(string strName, Secretary* strSub) { name = strName; sub = strSub; } void Update(); private: string name; Secretary* sub; }; // 秘书类(主题对象,通知者) class Secretary { public: string action; void Add(StockObserver ob) { observers.push_back(ob); } void Remove(int addIndex) { if(addIndex >=0 && addIndex < observers.size()) observers.erase(observers.begin() + addIndex); } void Notify() { vector<StockObserver>::iterator it; for (it=observers.begin(); it!=observers.end(); ++it) { (*it).Update(); } } private: vector<StockObserver> observers; }; void StockObserver::Update() { cout << name << " : " << sub->action << ", begin to work" << endl; } int main() { // 创建通知者 Secretary* p = new Secretary(); // 观察者 StockObserver* s1 = new StockObserver("Lazy", p); StockObserver* s2 = new StockObserver("SnowFire", p); // 加入通知队列 p->Add(*s1); p->Add(*s2); // 事件 p->action = "The boss is coming..."; // 通知 p->Notify(); // 动态删除 p->Remove(0); p->Notify(); return 0; }
适用性:
1.当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
2.当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
3.当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。
优缺点:
观察者模式的效果有以下几个优点:
1.观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体现察者聚集,每一个具体现察者都符合一个抽象观察者的接口。
被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
2.观察者模式支持广播通信。被观察者会向所有的登记过的观察者发出通知。
观察者模式有下面的一些缺点:
1.如果一个被观察者对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
2.如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察考模式时要特别注意这一点。
3.如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。
4.虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。