日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

C++ 通过模版工厂实现 简单反射机制

發布時間:2023/11/27 生活经验 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 通过模版工厂实现 简单反射机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

我們知道Java/Python這種語言能夠很好得 支持反射。反射機制 就是一種用戶輸入的字符串到對應實現方法的映射,比如http接口中 用戶傳入了url,我們需要調用該url對應的方法/函數對象 從而做出對應的操作。

而C++ 并沒有友好得支持這樣的操作,而最近工作中需要通過C++實現http接口,這個過程想要代碼實現得優雅一些,就需要實現這樣的功能。

最終的實現結果就是:

 int main() {Initial();JudgeName jm;auto res = jm.Judge("Zhang");res->ShowName();return 0;
}

我們只需要通過輸入一個字符串,就能得到一個字符串對應的類的對象,從而調用該對象對應的方法。

實現過程

  1. 實現模版工廠
    反射機制本身是依賴工廠模式實現的,也就是提供一個創建函數對象的工廠,能夠創建各種類型的函數對象。
    這里面的各種類型 – 其實就需要實現一個通用的模版工廠來達到創建各種類型的目的。

    // 工廠類模版,創建各種類型的類對象
    template <class OperationType_t>
    class OperationFactory {
    public:// 創建一個工廠單例,只會有一個對象工廠static OperationFactory<OperationType_t>& Instance() {static OperationFactory<OperationType_t> instance;return instance;}private:// We don't allow to constructor, copy constructor and align constructorOperationFactory() = default;~OperationFactory() = default;OperationFactory(const OperationFactory&) = delete;const OperationFactory& operator= (const OperationFactory&) = delete;};
    
  2. 實現類的對象到類名的映射。
    我們實現了能夠創建所有類對象的函數工廠,但是還需要將創建好的對象和他們的類名字對應起來,做一個映射。
    在模版工廠類中補充映射邏輯:

    // Factory class template
    template <class OperationType_t>
    class OperationFactory {
    public:// Single pattern of the factorystatic OperationFactory<OperationType_t>& Instance() {static OperationFactory<OperationType_t> instance;return instance;}// 類名 和 類對象的映射void RegisterOperation(const std::string& op_name,OperationRegister<OperationType_t>* reg) {operationRegister[op_name] = reg;}// 獲取指定類名字 對應的 對象// 也就是從映射map中查找OperationType_t* GetOperation(const std::string& op_name) {if (operationRegister.find(op_name) != operationRegister.end()) {return operationRegister[op_name]->CreateOperation(op_name);}return nullptr;}private:// We don't allow to constructor, copy constructor and align constructorOperationFactory() = default;~OperationFactory() = default;OperationFactory(const OperationFactory&) = delete;const OperationFactory& operator= (const OperationFactory&) = delete;// 類名字 和 類對象之間的映射std::map<std::string, OperationRegister<OperationType_t>* > operationRegister;
    };
    
  3. 實現一個注冊類
    此時 我們通過這個注冊類的入口 將類名 和類的對象完整映射起來。

    template <class OperationType_t>
    class OperationRegister {
    public:virtual OperationType_t* CreateOperation(const std::string& op_name) = 0;protected:OperationRegister() {}virtual ~OperationRegister() {}
    };// 注冊一個以基類的子類對象。
    template <class OperationType_t, class OperationImpl_t>
    class OperationImplRegister : public OperationRegister<OperationType_t> {
    public:// 獲取一個基類的工廠explicit OperationImplRegister(const std::string& op_name) {OperationFactory<OperationType_t>::Instance().RegisterOperation(op_name, this);}// 獲取這個基類對應的子類對象OperationType_t* CreateOperation(const std::string& op_name) {return new OperationImpl_t(op_name);}
    };
    

應用

有了上面的模版工廠 以及 注冊類名字 和 類的映射模版,接下來我們看看怎么使用:

我們實現了如下一個父類 以及 幾個父類對應的子類實現

class Father {
public:virtual std::string Name() = 0;virtual void ShowName() = 0;
};class Wang : public Father{
public:Wang(const std::string& name) : name_(name){}std::string Name() override { return name_; }void ShowName() override { cout << "Name: " << name_ << endl; }private:std::string name_;
};class Zhang : public Father {
public:Zhang(const std::string& name) : name_(name) {}std::string Name() override { return name_; }void ShowName() override { cout << "Name: " << name_ << endl; }private:std::string name_;
};class Li : public Father {
public:Li(const std::string& name) : name_(name) {}std::string Name() override { return name_; }void ShowName() override { cout << "Name: " << name_ << endl; }private:std::string name_;
};

接下來需要統一注冊一下這幾個子類 的 名字 以及他們的對象:

// Construct the string name with there object's map
void Initial() {static bool init = false;if (init == false) {static OperationImplRegister<Father, Wang> wang("Wang");static OperationImplRegister<Father, Zhang> zhang("Zhang");static OperationImplRegister<Father, Li> li("Li");init = true;}
}

最后就是一個通過字符串 獲取對象

class JudgeName {
public:JudgeName(){}Father* Judge(const std::string& name) {OperationFactory<Father>& fac = OperationFactory<Father>::Instance();return fac.GetOperation(name);}
};

這個類的函數中,我們用戶只需要傳入一個字符串,就能夠得到這個字符串的類的對象,從而進行后續的對象方法相關的操作。

能夠極大得簡化我們的if-else if 這樣的分支代碼,同時提升了代碼的可擴展性。用戶只需要繼續補充想要使用的類,并將這個類的名字和對象注冊到映射map中就好了,后續只需要使用類名就能夠創建出這個類的對象。

完整代碼實現

#include <iostream>
#include <map>using namespace std;// Register the operation
// The 'OperationTyple_t' is the abstract class
template <class OperationType_t>
class OperationRegister {
public:virtual OperationType_t* CreateOperation(const std::string& op_name) = 0;protected:OperationRegister() {}virtual ~OperationRegister() {}
};// Factory class template
template <class OperationType_t>
class OperationFactory {
public:// Single pattern of the factorystatic OperationFactory<OperationType_t>& Instance() {static OperationFactory<OperationType_t> instance;return instance;}void RegisterOperation(const std::string& op_name,OperationRegister<OperationType_t>* reg) {operationRegister[op_name] = reg;}OperationType_t* GetOperation(const std::string& op_name) {if (operationRegister.find(op_name) != operationRegister.end()) {return operationRegister[op_name]->CreateOperation(op_name);}return nullptr;}private:// We don't allow to constructor, copy constructor and align constructorOperationFactory() = default;~OperationFactory() = default;OperationFactory(const OperationFactory&) = delete;const OperationFactory& operator= (const OperationFactory&) = delete;std::map<std::string, OperationRegister<OperationType_t>* > operationRegister;
};// An template class to create the detail Operation
template <class OperationType_t, class OperationImpl_t>
class OperationImplRegister : public OperationRegister<OperationType_t> {
public:explicit OperationImplRegister(const std::string& op_name) {OperationFactory<OperationType_t>::Instance().RegisterOperation(op_name, this);}OperationType_t* CreateOperation(const std::string& op_name) {return new OperationImpl_t(op_name);}
};class Father {
public:virtual std::string Name() = 0;virtual void ShowName() = 0;
};class Wang : public Father{
public:Wang(const std::string& name) : name_(name){}std::string Name() override { return name_; }void ShowName() override { cout << "Name: " << name_ << endl; }private:std::string name_;
};class Zhang : public Father {
public:Zhang(const std::string& name) : name_(name) {}std::string Name() override { return name_; }void ShowName() override { cout << "Name: " << name_ << endl; }private:std::string name_;
};class Li : public Father {
public:Li(const std::string& name) : name_(name) {}std::string Name() override { return name_; }void ShowName() override { cout << "Name: " << name_ << endl; }private:std::string name_;
};// Construct the string name with there object's map
void Initial() {static bool init = false;if (init == false) {static OperationImplRegister<Father, Wang> wang("Wang");static OperationImplRegister<Father, Zhang> zhang("Zhang");static OperationImplRegister<Father, Li> li("Li");init = true;}
}class JudgeName {
public:JudgeName(){}Father* Judge(const std::string& name) {OperationFactory<Father>& fac = OperationFactory<Father>::Instance();return fac.GetOperation(name);}
};int main() {Initial();JudgeName jm;auto res = jm.Judge("Zhang");res->ShowName();return 0;
}

總結

以上是生活随笔為你收集整理的C++ 通过模版工厂实现 简单反射机制的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。