自動登録オブジェクトFactoryの実装方法
6546 ワード
ターゲット
C++の中のFactoryモードの応用シーン、実現方法を理解し、テンプレートを採用して実現することがもたらす便利さ.
ソース A C++ Object Factory Automatic object factory in C++ Register an object creator in object factory C++11自動登録工場 を実現
用途
一連のクラスはベースクラスから継承され、いずれもある動作を実行することができ、クラスのKeyに基づいてクラスインスタンスを取得して動作することができる.
元のバージョンと問題点
これは最も一般的な実装方法であり、クラスが追加されるとfactoryの作成方法を調整する必要があり、これらのコードがライブラリにカプセル化されると拡張する可能性はありません.クラス定義の調整を避け、できるだけ簡単に新しいクラスを登録できるように、不要な依存がないことを望んでいます.
実現構想.ベースクラス を準備する Factory単例 登録クラス構築方法 取得クラスインスタンス バージョンの調整
ベースクラス
Factoryの一例
クラス構築メソッドの登録
クラスインスタンスの構築
使用方法
新規クラス登録
マクロによる新規クラス登録
補助登録:
使用方法:
テンプレートを使用した新規クラス登録
補助登録:
使用方法:
自動登録の実装
以上のシナリオでは、構築メソッドの登録に静的変数を外部で定義する必要があります.また、外部定義を必要としない方法もあります.
静的変数をクラスにラップ
制約キー取得インタフェース
各クラス定義は、登録のためにKeyを取得するための静的インタフェース
補助クラスの定義
クラスの自動登録
Iはベースクラスであり、新しいクラスは
使用
登録補助クラスの調整
C++11の新しい特性:内部クラスは外部クラスのインスタンスを通じて外部クラスのプライベートメンバーにアクセスすることができる;
テンプレート登録の名前なし
マクロを使用して新しいクラス登録を行うと、静的アシストクラスインスタンス名が自動的にマージされますが、テンプレートを使用して新しいクラス登録を行うには、名前が重複しないことを保証する必要があります.そうしないと、コンパイルエラーが発生し、この問題を回避するには、次の方法を使用します.
その他の調整
C++11を参照して、自動的に登録されたファクトリを実装します.
factoryテンプレートを実現することで、統一されたfactoryを実現することができる.
学んだこと Factoryモードの実装 静的変数の自動登録等の処理における応用 マクロ の代わりにテンプレートを使用する方法
C++の中のFactoryモードの応用シーン、実現方法を理解し、テンプレートを採用して実現することがもたらす便利さ.
ソース
用途
一連のクラスはベースクラスから継承され、いずれもある動作を実行することができ、クラスのKeyに基づいてクラスインスタンスを取得して動作することができる.
元のバージョンと問題点
class IObject
{
public:
virtual void run() = 0;
virtual ~IObject() {};
};
class Object1:public IObject
{
public:
~Object1()
{
;
}
virtual void run() override
{
std::cout< create(const std::string& key)
{
if(key == "Object1")
return std::make_shared();
if(key == "Object2")
return std::make_shared();
return nullptr;
}
};
void original_test()
{
auto pVal1 = ObjectFactory::create("Object1");
auto pVal2 = ObjectFactory::create("Object2");
if(pVal1)
pVal1->run();
if(pVal2)
pVal2->run();
}
これは最も一般的な実装方法であり、クラスが追加されるとfactoryの作成方法を調整する必要があり、これらのコードがライブラリにカプセル化されると拡張する可能性はありません.クラス定義の調整を避け、できるだけ簡単に新しいクラスを登録できるように、不要な依存がないことを望んでいます.
実現構想.
ベースクラス
class IObject
{
public:
virtual void run() = 0;
virtual ~IObject() {};
};
Factoryの一例
class ObjectFactory
{
public:
static ObjectFactory* Instance()
{
static ObjectFactory factory;
return &factory;
}
};
クラス構築メソッドの登録
void registerObjectFunc(const std::string& name, std::function func)
{
funcs_[name] =func;
}
private:
std::map<:string>> funcs_;
クラスインスタンスの構築
std::shared_ptr create(const std::string& key)
{
auto it = funcs_.find(key);
if (it != funcs_.end())
return std::shared_ptr(it->second());
return nullptr;
}
使用方法
// 1
class Object1 :public IObject
{
public:
~Object1()
{
;
}
virtual void run() override
{
std::cout << "Object1
";
}
};
// 2
class Object2 :public IObject
{
public:
~Object2()
{
;
}
virtual void run() override
{
std::cout << "Object2
";
}
};
//
auto pVal1= ObjectFactory::Instance()->create("Object1");
auto pVal2 = ObjectFactory::Instance()->create("Object2");
if (pVal1)
pVal1->run();
if (pVal2)
pVal2->run();
新規クラス登録
static ObjectRegisterHelper Object1_ObjectRegisterHelper("Object1", []()->IObject* { return new Object1(); });
static ObjectRegisterHelper Object2_ObjectRegisterHelper("Object2", []()->IObject* { return new Object2(); });
マクロによる新規クラス登録
補助登録:
class ObjectRegisterHelper
{
public:
ObjectRegisterHelper(const char* key, std::function func)
{
ObjectFactory::Instance()->registerObjectFunc(key,func);
}
};
#define REGISTER_OBJECT(className,key) \
static ObjectRegisterHelper className##ObjectRegisterHelper(key,[]()->className*{ return new className();})
使用方法:
REGISTER_OBJECT(Object1,"Object1");
REGISTER_OBJECT(Object2, "Object2");
テンプレートを使用した新規クラス登録
補助登録:
template
class ObjectRegister
{
public:
ObjectRegister(const char* key)
{
ObjectFactory::Instance()->registerObjectFunc(key,[](){
return new T();
});
}
};
使用方法:
static ObjectRegister register1("Object1");
static ObjectRegister register2("Object2");
自動登録の実装
以上のシナリオでは、構築メソッドの登録に静的変数を外部で定義する必要があります.また、外部定義を必要としない方法もあります.
静的変数をクラスにラップ
制約キー取得インタフェース
各クラス定義は、登録のためにKeyを取得するための静的インタフェース
Key()
を有する.template
void registerT()
{
//std::cout << "RegisterT " << T::Key() << "
";
funcs_[T::Key()] = []()->IEntry* { return new T(); };
}
補助クラスの定義
template
struct RegisterClass
{
RegisterClass()
{
Factory::Instance().registerT();
}
};
クラスの自動登録
Iはベースクラスであり、新しいクラスは
AutoRegister
自動付帯登録クラスから継承されるtemplate
struct AutoRegister :public I
{
AutoRegister()
{
//®ister_;
}
public:
static RegisterClass register_;
};
// ->(C++14 )
template
RegisterClass AutoRegister::register_;
使用
class Object :public AutoRegister
登録補助クラスの調整
C++11の新しい特性:内部クラスは外部クラスのインスタンスを通じて外部クラスのプライベートメンバーにアクセスすることができる;
struct Factory
{
public:
template
struct register_helper
{
register_helper(const char* key)
{
//
Instance().funcs_[key] = []()->IEntry* { return new T(); };
}
};
テンプレート登録の名前なし
マクロを使用して新しいクラス登録を行うと、静的アシストクラスインスタンス名が自動的にマージされますが、テンプレートを使用して新しいクラス登録を行うには、名前が重複しないことを保証する必要があります.そうしないと、コンパイルエラーが発生し、この問題を回避するには、次の方法を使用します.
template
struct register_agent
{
static Factory::register_helper helper;
};
//TObject
decltype(register_agent::helper) register_agent::helper("TObject");
//Object
decltype(register_agent
その他の調整
C++11を参照して、自動的に登録されたファクトリを実装します.
factoryテンプレートを実現することで、統一されたfactoryを実現することができる.
学んだこと