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,在使用之前需要對多份消息進行注冊,當有消息過來時便可以進行通知.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM