设计模式之观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。其UML图如下:
在ConcretSubject内部有一个Observer的列表,当Subject的状态发生改变时,会通知列表内的所有的观察者。而观察者都实现了统一的接口,而不同的观察者在该接口中做出了不同的响应。其示例代码如下:
1 // ObserverModel.h文件 2 #pragma once 3 #include <iostream> 4 #include <vector> 5 #include <string> 6 #include <algorithm> 7 // 观察者 8 class Observer 9 { 10 public: 11 virtual void Update() = 0; 12 }; 13 14 class ConcreteObserver_0 : public Observer 15 { 16 public: 17 virtual void Update() 18 { 19 std::cout << "ConcreteObserver_0 知道了" << std::endl; 20 } 21 }; 22 23 class ConcreteObserver_1 : public Observer 24 { 25 public: 26 virtual void Update() 27 { 28 std::cout << "ConcreteObserver_1 知道了" << std::endl; 29 } 30 }; 31 // 通知者 32 class Subject 33 { 34 public: 35 virtual void Attatch(Observer * p) = 0; 36 virtual void Detach(Observer * p) = 0; 37 virtual void Notify() = 0; 38 virtual void changeState(std::string str) 39 { 40 m_str = str; 41 Notify(); 42 } 43 44 protected: 45 std::string m_str; 46 }; 47 // 传统观察者模式 48 class ConcreteSubject : public Subject 49 { 50 public: 51 ConcreteSubject() 52 { 53 ; 54 } 55 ~ConcreteSubject() 56 { 57 m_vec.clear(); 58 } 59 virtual void Attatch(Observer * p) 60 { 61 m_vec.push_back(p); 62 } 63 virtual void Detach(Observer * p) 64 { 65 auto it = find(m_vec.begin(), m_vec.end(), p); 66 if (m_vec.end() != it) 67 { 68 m_vec.erase(it); 69 } 70 } 71 virtual void Notify() 72 { 73 for (auto it = m_vec.cbegin(); it != m_vec.cend(); it++) 74 { 75 std::cout << m_str << " "; 76 (*it)->Update(); 77 } 78 } 79 private: 80 std::vector<Observer * > m_vec; 81 };
测试代码如下:
1 #include <iostream> 2 #include "ObserverModel.h" 3 4 int main() 5 { 6 using namespace std; 7 // 观察者模式 8 ConcreteSubject * p = new ConcreteSubject(); 9 Observer * p1 = new ConcreteObserver_0(); 10 Observer * p2 = new ConcreteObserver_1(); 11 p->Attatch(p1); 12 p->Attatch(p2); 13 p->changeState("老板来啦"); 14 delete p; 15 delete p2; 16 delete p1; 17 18 getchar(); 19 return 0; 20 }
测试结果如下图:
观察者模式也有不足,观察者模式需要观察者需要实现相同的接口。但是如果已经些好的类或者第三方的类库则就没办法实现该功能了。所以可以稍稍改进一下,就是把Subject类中的关于观察者的列表修改为函数指针的列表。示例码如下:
1 // ObserverModel.h文件 2 #pragma once 3 #include <iostream> 4 #include <vector> 5 #include <string> 6 #include <algorithm> 7 // 函数指针版本 8 class ConcreteObserverFunc_0 9 { 10 public: 11 static void func_0() 12 { 13 std::cout << "ConcreteObserver_0 知道了" << std::endl; 14 } 15 }; 16 17 class ConcreteObserverFunc_1 18 { 19 public: 20 static void func_1() 21 { 22 std::cout << "ConcreteObserver_1 知道了" << std::endl; 23 } 24 }; 25 26 class SubjectFunc 27 { 28 public: 29 virtual void Attatch(void (*p)()) = 0; 30 virtual void Detach(void(*p)()) = 0; 31 virtual void Notify() = 0; 32 virtual void changeState(std::string str) 33 { 34 m_str = str; 35 Notify(); 36 } 37 protected: 38 std::string m_str; 39 }; 40 41 class ConcreteSubjectFunc : public SubjectFunc 42 { 43 private: 44 std::vector<void(*)()> m_func; 45 public: 46 ConcreteSubjectFunc() 47 { 48 ; 49 } 50 ~ConcreteSubjectFunc() 51 { 52 m_func.clear(); 53 } 54 virtual void Attatch(void (*p)()) 55 { 56 m_func.push_back(p); 57 } 58 virtual void Detach(void(*p)()) 59 { 60 auto it = find(m_func.begin(), m_func.end(), p); 61 if (m_func.end() != it) 62 { 63 m_func.erase(it); 64 } 65 } 66 virtual void Notify() 67 { 68 for (auto it = m_func.cbegin(); it != m_func.cend(); it++) 69 { 70 std::cout << m_str << " "; 71 (*it)(); 72 } 73 } 74 };
测试代码如下:
1 #include <iostream> 2 #include "ObserverModel.h" 3 4 int main() 5 { 6 using namespace std; 7 // 观察者模式 8 ConcreteObserverFunc_0 * p1Func = new ConcreteObserverFunc_0(); 9 ConcreteObserverFunc_1 * p2Func = new ConcreteObserverFunc_1(); 10 ConcreteSubjectFunc * pFunc = new ConcreteSubjectFunc(); 11 pFunc->Attatch(&ConcreteObserverFunc_0::func_0); 12 pFunc->Attatch(&ConcreteObserverFunc_1::func_1); 13 pFunc->changeState("我的天哪"); 14 delete p1Func; 15 delete p2Func; 16 delete pFunc; 17 18 getchar(); 19 return 0; 20 }
测试结果如下图:
标签:ConcreteObserverFunc,设计模式,void,观察者,C++,func,new,include From: https://www.cnblogs.com/ybqjymy/p/17535007.html