C++11之用std::function和std::bind实现观察者模式

使用C++11中的std::bind和std::function以及模板可以很好的实现观察者模式,现在把自己的一些实现的想法记录在此.

编译环境:VS2017

实现的想法:将各个类之间进行解耦,使用C++11的特性实现观察者,C++11中的std::function中可以传函数和lambda仿函数,感觉类似标准之前的回调函数,有时间会去剖析一下该特性.

观察者模式简介:

主体类中维护一个观察者的列表,如果有消息传过来,列表将把所有的消息遍历一遍,一般列表元素是一个父类指针,利用继承的特性实现子类中的相应.

类似于此:

class Subject
{
public:
    std::vector<Base*>m_vec;
};

利用模板的静态多态去取代继承的动态多态.

如此实现的话会造成各个模块之间的耦合过强,对子类的修改也会影响到父类。

更改的代码如下:

1 使用std::function在调用之前完成对列表元素的添加(可以称之为注册)

2 利用模板实现类型的推导

3 使用std::map来存储数据,用于当作主体中的观察者列表

code 如下:

 1 #include "pch.h"
 2 #include <iostream>
 3 #include <vector>
 4 #include <functional>
 5 #include <map>
 6 
 7 template<typename EVENT>
 8 class Subject
 9 {
10 public:
11     template<typename OBSERVER>
12     void registerObser(const EVENT&event, OBSERVER&&observer)
13     {
14         m_map_observers[event].push_back(std::forward<OBSERVER>(observer));
15     }
16     
17     void notify(const EVENT&event)const
18     {
19         for (auto &itor : m_map_observers.at(event))
20         {
21             itor();
22         }
23     }
24 
25 private:
26     std::map<EVENT, std::vector<std::function<void()>>> m_map_observers;
27 };
28 
29 
30 class Derive1 
31 {
32 public:
33     
34     void printMsg() { std::cout << __func__ << std::endl; }
35 };
36 
37 class Derive2
38 {
39 public:
40     void printMsg(int level) { std::cout << __func__ << "level is " << level << std::endl; }
41 };
42 
43 class VarDef
44 {
45 public:
46     VarDef(std::string s1) :m_s1(s1) {}
47     VarDef(std::string s1, int level) :m_s1(s1), m_level(level) {}
48     std::string m_s1;
49     int m_level;
50     friend bool operator<(const VarDef&left, const VarDef&right)
51     {
52         if (left.m_s1 == right.m_s1)
53             return (left.m_level < right.m_level);
54         else
55             return (left.m_s1 < right.m_s1);
56     }
57 };
58 
59 int main()
60 {
61     Subject<VarDef> s;
62     
63     s.registerObser(VarDef("Derive1"), std::bind(&Derive1::printMsg, &Derive1()));
64     s.registerObser(VarDef("Derive2", 2), std::bind(&Derive2::printMsg, &Derive2(),2));
65 
66     s.notify(VarDef("Derive2",2));
67 
68     return 0;
69 }

实现功能:
维护类VarDef来实现针对不同Message的打印.在该类中需要定义多个构造函数来完成不同的功能.

对外暴露的接口为registerObser,notify,在使用之前需要对多份消息进行注册,当有消息过来时便可以进行通知.

猜你喜欢

转载自www.cnblogs.com/Kaifangqu/p/11406676.html
今日推荐