C++设计模式之观察者模式

发布时间 2023-07-07 15:01:37作者: 一杯清酒邀明月

设计模式之观察者模式

观察者模式定义了一种一对多的依赖关系,让多个观察者同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。其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 }

测试结果如下图: