简述:
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够主动更新自己。
观察者模式包括:抽象主题类、具体主题类、抽象观察者类、具体观察者类。
抽象主题类:它把所有对观察者对象的指针保存在一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
具体主题类:具体主题,将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有登记过的观察者发出通知。
抽象观察者类:抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。
具体观察者类:具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。
观察者模式代码:C++与C#的区别要注意相互包含的问题,同时要注意声明顺序。
1 #include <iostream> 2 #include <list> 3 using namespace std; 4 5 // 抽象观察者类 6 class CObserver 7 { 8 public: 9 virtual void UpDate() {} 10 }; 11 12 // 抽象通知者类 13 class CSubject 14 { 15 private: 16 list<CObserver*> m_listObserver; 17 18 public: 19 virtual void Attach(CObserver* pObserver) 20 { 21 m_listObserver.push_back(pObserver); 22 } 23 24 virtual void Detach(CObserver* pObserver) 25 { 26 m_listObserver.remove(pObserver); 27 } 28 29 virtual void Notify() 30 { 31 for (CObserver* pObserver : m_listObserver) 32 pObserver->UpDate(); 33 } 34 }; 35 36 // 具体通知者类 37 class CConcreteSubject : public CSubject 38 { 39 private: 40 string m_szSubjectState; 41 42 public: 43 void SetSubjectState(string szSubjectState) 44 { 45 m_szSubjectState = szSubjectState; 46 } 47 48 string GetSubjectState() 49 { 50 return m_szSubjectState; 51 } 52 }; 53 54 // 具体观察者类 55 class CConcreteObserver : public CObserver 56 { 57 private: 58 string m_szName; 59 CConcreteSubject* m_pSubject; 60 61 public: 62 CConcreteObserver(CConcreteSubject* pSubject, string szName) 63 { 64 m_szName = szName; 65 m_pSubject = pSubject; 66 } 67 68 virtual void UpDate() 69 { 70 cout << "观察者[" << m_szName << "]的新状态是[" 71 << m_pSubject->GetSubjectState() << "]" << endl; 72 } 73 74 void SetSubject(CConcreteSubject* pSubject) 75 { 76 m_pSubject = pSubject; 77 } 78 79 CSubject* GetSubject() 80 { 81 return m_pSubject; 82 } 83 }; 84 85 int main() 86 { 87 CConcreteSubject ConcreteSubject; 88 CConcreteObserver ConcreteObserver1(&ConcreteSubject, "X"); 89 CConcreteObserver ConcreteObserver2(&ConcreteSubject, "Y"); 90 CConcreteObserver ConcreteObserver3(&ConcreteSubject, "Z"); 91 92 ConcreteSubject.Attach(&ConcreteObserver1); 93 ConcreteSubject.Attach(&ConcreteObserver2); 94 ConcreteSubject.Attach(&ConcreteObserver3); 95 96 ConcreteSubject.Detach(&ConcreteObserver2); 97 98 ConcreteSubject.SetSubjectState("ABC"); 99 100 ConcreteSubject.Notify(); 101 102 system("pause"); 103 return 0; 104 }
输出结果:
注:C++是没有C#中的委托事件这种语法的,但是可以用函数指针来实现,笔者比较懒,没写。
例:前台监测老板是否回来了。
代码如下:
1 #include <iostream> 2 #include <list> 3 using namespace std; 4 5 class CSubject; 6 // 抽象观察者类 7 class CObserver 8 { 9 protected: 10 string m_szName; 11 CSubject* m_pSubject; 12 13 public: 14 CObserver(string szName, CSubject* pSubject) : m_szName(szName), m_pSubject(pSubject) {}; 15 virtual ~CObserver() {}; 16 virtual void UpDate() {}; 17 }; 18 19 // 抽象主题类 20 class CSubject 21 { 22 private: 23 list<CObserver*> m_listCObserver; 24 string m_szAction; 25 26 public: 27 CSubject() {}; 28 virtual ~CSubject() 29 { 30 if (!m_listCObserver.empty()) 31 { 32 m_listCObserver.clear(); 33 } 34 } 35 36 virtual void Attach(CObserver* pObserver) 37 { 38 m_listCObserver.push_back(pObserver); 39 } 40 41 virtual void Detach(CObserver* pDelObserver) 42 { 43 if (!m_listCObserver.empty()) 44 { 45 m_listCObserver.remove(pDelObserver); 46 } 47 } 48 49 virtual void Notify() 50 { 51 for (CObserver* pObserver : m_listCObserver) 52 { 53 pObserver->UpDate(); 54 } 55 } 56 57 void SetSubjectState(string szAction) 58 { 59 m_szAction = szAction; 60 } 61 62 string GetSubjectState() 63 { 64 return m_szAction; 65 } 66 }; 67 68 // 看股票的同事(具体观察者类) 69 class CStockObserver : public CObserver 70 { 71 public: 72 CStockObserver(string szName, CSubject* pSubject) 73 : CObserver(szName, pSubject) {} 74 75 virtual ~CStockObserver() {} 76 77 virtual void UpDate() 78 { 79 cout << "[" << m_pSubject->GetSubjectState() << "]" 80 << "[" << m_szName << "]" << "关闭股票行情,继续工作。。。" << endl; 81 } 82 }; 83 84 // 看NBA的同事(具体观察者类) 85 class CNBAObserver : public CObserver 86 { 87 public: 88 CNBAObserver(string szName, CSubject* pSubject) 89 : CObserver(szName, pSubject) {} 90 91 virtual ~CNBAObserver() {} 92 93 virtual void UpDate() 94 { 95 cout << "[" << m_pSubject->GetSubjectState() << "]" 96 << "[" << m_szName << "]" << "关闭NBA直播,继续工作。。。" << endl; 97 } 98 }; 99 100 // 我嫌麻烦,把具体主题类的共有内容放到抽象主题类里写了,懒得写两遍 101 // 老板(具体主题类) 102 class CBoss : public CSubject 103 { 104 }; 105 106 // 秘书(具体主题类) 107 class CReception : public CSubject 108 { 109 }; 110 111 // C++资源回收,记住哪里创建就要哪里释放 112 // 其他作用域只是指针传递,如果在别的地方释放,容易导致多次释放报错 113 int main() 114 { 115 CBoss Boss; 116 117 CStockObserver StockObserver("GHL", &Boss); 118 CNBAObserver NBAObserver("GGG", &Boss); 119 120 Boss.Attach(&StockObserver); 121 Boss.Attach(&NBAObserver); 122 123 Boss.SetSubjectState("我胡汉三回来了!"); 124 125 Boss.Notify(); 126 127 128 cout << " 华丽的分割线 " << endl; 129 CReception Reception; 130 131 CStockObserver StockObserve1("123", &Reception); 132 CNBAObserver NBAObserve1("456", &Reception); 133 134 Reception.Attach(&StockObserve1); 135 Reception.Attach(&NBAObserve1); 136 Reception.Detach(&NBAObserve1); 137 138 Reception.SetSubjectState("老板回来了!"); 139 140 Reception.Notify(); 141 142 system("pause"); 143 return 0; 144 }
输出结果: