觀察者模式實現(模仿CSharpMessenger擴充套件)
阿新 • • 發佈:2018-12-11
我們在遊戲開發中經常會用到這種模式,用於模組之間的訊息分發,來降低模組之間耦合性,基本原來就是利用字串作為key值來儲存回撥函式(大多數觀察者模式使用字串作為訊息佇列中的key值),分發訊息時檢索key值來獲取回撥函式並執行來達到模組之間互動的功能,為了實現訊息型別拓展,這裡我使用了類模板來實現,由於c++編譯器對類模板的限制,因此類模板成員函式的實現我也放在了標頭檔案中,程式碼之中不作說明
標頭檔案:
#include <iostream> #include <vector> #include <map> //訊息系統 //無引數 class Message { public: typedef void(*CallBack)(); Message() {} ~Message() { messageMap.clear(); } static Message* instance; void Clean(); static Message* GetInstance(); void AddListener(std::string eventType, CallBack callback); void RemoveListener(std::string eventType, CallBack callback); void Dispatch(std::string eventType); private: std::map<std::string, std::vector<CallBack>> messageMap; }; //單引數 template<class T> class MessageI { public: typedef void(*CallBack)(T args); MessageI() {} static MessageI<T>* GetInstance(); void AddListener(std::string eventType, CallBack callback); void RemoveListener(std::string eventType, CallBack callback); void Dispatch(std::string eventType, T arg1); void Clean(); private: std::map<std::string, std::vector<CallBack> > messageMap; static MessageI<T>* instanceI; }; template<class T> MessageI<T>* MessageI<T>::instanceI = NULL; template<class T> MessageI<T>* MessageI<T>::GetInstance() { if (!instanceI) { instanceI = new MessageI<T>(); } return instanceI; } template<class T> void MessageI<T>::Clean() { messageMap.clear(); } template<class T> void MessageI<T>::AddListener(std::string eventType, CallBack callback) { auto iter = messageMap.find(eventType); if (iter != messageMap.end()) { iter->second.push_back(callback); } else { vector<CallBack> temp; temp.push_back(callback); messageMap.insert(make_pair(eventType, temp)); } } template<class T> void MessageI<T>::RemoveListener(std::string eventType, CallBack callback) { auto iter = messageMap.find(eventType); if (iter == messageMap.end()) { cout << "error:刪除不存在的訊息 name = " << eventType.c_str() << endl; } else { auto funcVec = iter->second; for (auto iter = funcVec.begin(); iter != funcVec.end(); iter++) { if (*iter == callback) { funcVec.erase(iter); break; } } if (funcVec.size == 0) { messageMap.erase(iter); } } } template<class T> void MessageI<T>::Dispatch(std::string eventType, T arg1) { auto iter = messageMap.find(eventType); if (iter == messageMap.end()) { cout << "error:觸發不存在的訊息 name = " << eventType.c_str() << endl; } else { auto funcVec = iter->second; for each (auto var in funcVec) { if (var) { var(arg1); } else { cout << "error:回撥函式為null name = " << eventType.c_str() << endl; } } } } //兩個引數 template<class T, class U> class MessageII { public: typedef void(*CallBack)(T args1, U args2); MessageII() {} static MessageII<T, U>* GetInstance(); void AddListener(std::string eventType, CallBack callback); void RemoveListener(std::string eventType, CallBack callback); void Dispatch(std::string eventType, T args1, U args2); void Clean(); private: std::map<std::string, std::vector<CallBack> > messageMap; static MessageII<T, U>* instanceII; }; template<class T, class U> MessageII<T, U>* MessageII<T, U>::instanceII = NULL; template<class T, class U> MessageII<T, U>* MessageII<T, U>::GetInstance() { if (!instanceII) { instanceII = new MessageII<T, U>(); } return instanceII; } template<class T, class U> void MessageII<T, U>::Clean() { messageMap.clear(); } template<class T, class U> void MessageII<T, U>::AddListener(std::string eventType, CallBack callback) { auto iter = messageMap.find(eventType); if (iter != messageMap.end()) { iter->second.push_back(callback); } else { vector<CallBack> temp; temp.push_back(callback); messageMap.insert(make_pair(eventType, temp)); } } template<class T, class U> void MessageII<T, U>::RemoveListener(std::string eventType, CallBack callback) { auto iter = messageMap.find(eventType); if (iter == messageMap.end()) { cout << "error:刪除不存在的訊息 name = " << eventType.c_str() << endl; } else { auto funcVec = iter->second; for (auto iter = funcVec.begin(); iter != funcVec.end(); iter++) { if (*iter == callback) { funcVec.erase(iter); break; } } if (funcVec.size == 0) { messageMap.erase(iter); } } } template<class T, class U> void MessageII<T, U>::Dispatch(std::string eventType, T args1, U args2) { auto iter = messageMap.find(eventType); if (iter == messageMap.end()) { cout << "error:觸發不存在的訊息 name = " << eventType.c_str() << endl; } else { auto funcVec = iter->second; for each (auto var in funcVec) { if (var) { var(args1, args2); } else { cout << "error:回撥函式為null name = " << eventType.c_str() << endl; } } } }
原始檔:
#include "stdafx.h" #include "Message.h" using namespace std; Message* Message::instance = nullptr; Message* Message::GetInstance() { if (instance == nullptr) { instance = new Message(); } return instance; } void Message::Clean() { messageMap.clear(); } void Message::AddListener(string eventType, CallBack callback) { auto iter = messageMap.find(eventType); if (iter != messageMap.end()) { iter->second.push_back(callback); } else { vector<CallBack> temp; temp.push_back(callback); messageMap.insert(make_pair(eventType, temp)); } } void Message::RemoveListener(string eventType, CallBack callback) { auto iter = messageMap.find(eventType); if (iter == messageMap.end()) { cout << "error:刪除不存在的訊息 name = "<<eventType.c_str()<<endl; } else { auto funcVec = iter->second; for (auto iter = funcVec.begin(); iter != funcVec.end(); iter++) { if (*iter == callback) { funcVec.erase(iter); break; } } if (funcVec.size() == 0) { messageMap.erase(iter); } } } void Message::Dispatch(string eventType) { auto iter = messageMap.find(eventType); if (iter == messageMap.end()) { cout << "error:觸發不存在的訊息 name = " << eventType.c_str() << endl; } else { auto funcVec = iter->second; for each (auto var in funcVec) { if (var) { var(); } else { cout << "error:回撥函式為null name = " << eventType.c_str() << endl; } } } }
當前實現了無參訊息分發、一個引數訊息分發、兩個引數訊息分發,後續有需求可以對照拓展即可
使用例子如下:
// EventTest.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include <iostream> #include "Message.h" using namespace std; void pint() { cout << "a" << endl; } void pint2() { cout << "b" << endl; } void test1(int a) { cout<<"call test1 value = " << a << endl; } void test2(int b) { cout << "call test2 value = " << b << endl; } void test3(int a, string str) { cout << "a = " << a << ", str = " << str.c_str() << endl; } void test4(string str1, string str2) { cout << "str1 = " << str1.c_str() << ", str2 = " << str2.c_str() << endl; } int main() { Message::GetInstance()->AddListener("test", pint); Message::GetInstance()->AddListener("test", pint2); Message::GetInstance()->Dispatch("test"); MessageI<int>::GetInstance()->AddListener("test", test1); MessageI<int>::GetInstance()->AddListener("test", test2); MessageI<int>::GetInstance()->Dispatch("test", 10); MessageII<int, string>::GetInstance()->AddListener("test", test3); MessageII<string, string>::GetInstance()->AddListener("test", test4); MessageII<int, string>::GetInstance()->Dispatch("test", 15, "HelloWorld"); MessageII<string, string>::GetInstance()->Dispatch("test", "ko", "HelloWorld"); system("pause"); return 0; }
輸出: