观察者模式
【1】什么是观察者模式?
观察者模式,定义一种一对多的依赖关系,多个观察者对象同时监听某一个主题对象。
当这个主题对象状态上发生变化时,会通知所有观察者对象,他们能够自动更新自己,随主题对象状态改变做出对应的行为表现。
【2】观察者模式代码示例:
代码示例如下:
1 #include <iostream> 2 #include <string> 3 #include <list> 4 using namespace std; 5 6 class Observer; 7 8 // 管理观察者的基类 9 class Subject 10 { 11 public: 12 string action; // 主题名称 13 protected: 14 list<Observer*> observers; // 观察者的容器 15 16 public: 17 virtual void attach(Observer*) = 0; 18 virtual void detach(Observer*) = 0; 19 virtual void notify() = 0; 20 }; 21 22 // 观察者基类 23 class Observer 24 { 25 protected: 26 string name; 27 Subject *sub; 28 29 public: 30 Observer(string name, Subject *sub) 31 { 32 this->name = name; 33 this->sub = sub; 34 } 35 string getName() 36 { 37 return name; 38 } 39 40 virtual void update() = 0; 41 }; 42 43 // 炒股票(观察者其一) 44 class StockObserver : public Observer 45 { 46 public: 47 StockObserver(string name, Subject *sub) : Observer(name, sub) 48 {} 49 50 void update(); 51 }; 52 53 void StockObserver::update() 54 { 55 cout << name << " 收到消息:" << sub->action << endl; 56 if (sub->action == "梁所长来了!") 57 { 58 cout << "我马上关闭股票,装做很认真工作的样子!" << endl; 59 } 60 } 61 62 // 看NBA比赛(观察者其一) 63 class NBAObserver : public Observer 64 { 65 public: 66 NBAObserver(string name, Subject *sub) : Observer(name, sub) 67 {} 68 void update(); 69 }; 70 71 void NBAObserver::update() 72 { 73 cout << name << " 收到消息:" << sub->action << endl; 74 if (sub->action == "梁所长来了!") 75 { 76 cout << "我马上关闭NBA,装做很认真工作的样子!" << endl; 77 } 78 } 79 80 // 玩游戏(观察者其一) 81 class GameObserver : public Observer 82 { 83 public: 84 GameObserver(string name, Subject *sub) : Observer(name, sub) 85 {} 86 87 void update(); 88 }; 89 90 void GameObserver::update() 91 { 92 cout << name << " 收到消息:" << sub->action << endl; 93 if (sub->action == "梁所长来了!") 94 { 95 cout << "我马上退出游戏,装做很认真工作的样子!" << endl; 96 } 97 } 98 99 // 管理观察者的实现类(作为被观察者) 100 class Secretary : public Subject 101 { 102 public: 103 void attach(Observer *observer) 104 { 105 cout << "add: " << observer->getName() << endl; 106 observers.push_back(observer); 107 } 108 109 void detach(Observer *observer) 110 { 111 list<Observer *>::iterator iter = observers.begin(); 112 while (iter != observers.end()) 113 { 114 if ((*iter) == observer) 115 { 116 cout << "erase: " << observer->getName() << endl; 117 observers.erase(iter++); 118 } 119 else 120 { 121 ++iter; 122 } 123 } 124 } 125 126 void notify() 127 { 128 list<Observer *>::iterator iter = observers.begin(); 129 while (iter != observers.end()) 130 { 131 (*iter)->update(); 132 ++iter; 133 } 134 } 135 }; 136 137 138 void main() 139 { 140 Subject *pDwq = new Secretary(); // 主题对象,作为被观察者 141 142 Observer *pXs = new NBAObserver("xiaoshuai", pDwq); // 小帅,作为观察者(监听者) 143 Observer *pZy = new GameObserver("zhuoyue", pDwq); // 卓越,作为观察者(监听者) 144 Observer *pLm = new StockObserver("liming", pDwq); // 李明,作为观察者(监听者) 145 146 // 绑定观察者与被观察者 147 cout << "登记监听者: " << endl; 148 pDwq->attach(pXs); 149 pDwq->attach(pZy); 150 pDwq->attach(pLm); 151 152 // 测试广播动作 153 cout << endl << "测试广播动作效果: " << endl; 154 cout << "发出动作1效果:去吃饭了!" << endl; 155 pDwq->action = "去吃饭了!"; 156 pDwq->notify(); 157 158 cout << endl << "发出动作2效果:梁所长来了!" << endl; 159 pDwq->action = "梁所长来了!"; 160 pDwq->notify(); 161 162 // 解除绑定监听 163 cout << endl << "解除监听者: " << endl; 164 pDwq->detach(pLm); 165 pDwq->detach(pZy); 166 pDwq->detach(pXs); 167 168 delete pDwq; 169 delete pXs; 170 delete pZy; 171 delete pLm; 172 173 system("pause"); 174 } 175 176 // run out: 177 /* 178 登记监听者: 179 add: xiaoshuai 180 add: zhuoyue 181 add: liming 182 183 测试广播动作效果: 184 发出动作1效果:去吃饭了! 185 xiaoshuai 收到消息:去吃饭了! 186 zhuoyue 收到消息:去吃饭了! 187 liming 收到消息:去吃饭了! 188 189 发出动作2效果:梁所长来了! 190 xiaoshuai 收到消息:梁所长来了! 191 我马上关闭NBA,装做很认真工作的样子! 192 zhuoyue 收到消息:梁所长来了! 193 我马上退出游戏,装做很认真工作的样子! 194 liming 收到消息:梁所长来了! 195 我马上关闭股票,装做很认真工作的样子! 196 197 解除监听者: 198 erase: liming 199 erase: zhuoyue 200 erase: xiaoshuai 201 请按任意键继续. . .
【3】观察者模式的优缺点
观察者模式的效果有以下的优点:
第一、观察者模式在被观察者和观察者之间建立一个抽象的耦合。
被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。
被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。
由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。如果被观察者和观察者都被扔到一起,那么这个对象必然跨越抽象化和具体化层次。
第二、观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知。
观察者模式有下面的缺点:
第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
第二、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。
第三、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。
第四、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。
Good Good Study, Day Day Up.
顺序 选择 循环 总结