Observer(观察者)
20. Observer(观察者)
20.1 定义
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新
20.2 优点
■ 观察者和被观察者之间是抽象耦合。被观察者角色所知道的只是一个具体观察者集合,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体的观察者,它只知道它们都有一个共同的接口。由于被观察者和观察者没有紧密的耦合在一起,因此它们可以属于不同的抽象化层次,且都非常容易扩展。
■ 支持广播通信。被观察者会向所有登记过的观察者发出通知,这就是一个触发机制,形成一个触发链。
20.3 缺点
■ 如果一个主题有多个直接或间接的观察者,则通知所有的观察者会花费很多时间,且开发和调试都比较复杂。
■ 如果在主题之间有循环依赖,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式时要特别注意这一点。
■ 如果对观察者的通知是通过另外的线程进行异步投递,系统必须保证投递的顺序执行。
■ 虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有提供相应的机制使观察者知道所观察的对象是如何发生变化。
20.4. 应用场景
■ 关联行为场景。
■ 事件多级触发场景
■ 跨系统的消息交换场景,如消息队列的处理机制
1 #include<iostream> 2 #include<vector> 3 using namespace std; 4 class Clickable; 5 class ClickabkeObserver; 6 7 class Clickable{ 8 public: 9 virtual void click() = 0; 10 virtual void addClickableObserver(ClickabkeObserver* observer) = 0; 11 virtual void removeClickableObserver(ClickabkeObserver* observer) = 0; 12 }; 13 class ClickabkeObserver{ 14 public: 15 virtual void click(Clickable* clickable) = 0; 16 }; 17 class Button:public Clickable{ 18 public: 19 vector<ClickabkeObserver*>observers; 20 string color; 21 int x,y; 22 void click(){ 23 cout<<"按钮被单击"<<endl; 24 for(int i=observers.size()-1;i>=0;i--){ 25 observers[i]->click(this); 26 } 27 } 28 void addClickableObserver(ClickabkeObserver* observer){ 29 observers.push_back(observer); 30 } 31 void removeClickableObserver(ClickabkeObserver* observer){ 32 33 } 34 }; 35 class ChangeCoordinateObserver:public ClickabkeObserver{ 36 public: 37 void click(Clickable* clickable){ 38 Button* b = (Button*)clickable; 39 b->x = 100; 40 b->y = 90; 41 } 42 }; 43 class ChangeColorObserver:public ClickabkeObserver{ 44 public: 45 void click(Clickable* clickable){ 46 Button* b = (Button*)clickable; 47 b->color = "red"; 48 } 49 }; 50 class OtherObserver:public ClickabkeObserver{ 51 public: 52 void click(Clickable* clickable){ 53 cout<<"其他操作"<<endl; 54 } 55 }; 56 int main(){ 57 Button* button = new Button(); 58 button->color = "blue"; 59 button->x = 0; 60 button->y = 0; 61 button->addClickableObserver(new ChangeColorObserver()); 62 button->addClickableObserver(new OtherObserver()); 63 button->click(); 64 cout<<"颜色:"<<button->color<<"坐标("<<button->x<<button->y<<")"<<endl; 65 }
我心自有明月在,不堕地狱不跪佛