編集: 回答のコメントに続くマイナーな修正 (仮想印刷; mpInstance を返す)。
任意の基本クラスから子クラスを派生できるシステムを作成しようとしています。その実装は、基本クラスの実装を置き換える必要があります。
基本クラス オブジェクトを作成および使用するすべてのオブジェクトは、オブジェクトの作成または呼び出しの方法を変更してはなりません。つまり、実際に Child クラスを作成するときでも、BaseClass.Create() を呼び出し続ける必要があります。基本クラスは、オーバーライドできることを認識していますが、それらをオーバーライドする具象クラスは認識していません。
そして、すべての Child クラスの登録を 1 か所で行うようにしたいと考えています。
これが私の実装です:
class CAbstractFactory
{
public:
virtual ~CAbstractFactory()=0;
};
template<typename Class>
class CRegisteredClassFactory: public CAbstractFactory
{
public:
~CRegisteredClassFactory(){};
Class* CreateAndGet()
{
pClass = new Class;
return pClass;
}
private:
Class* pClass;
};
// holds info about all the classes that were registered to be overridden
class CRegisteredClasses
{
public:
bool find(const string & sClassName);
CAbstractFactory* GetFactory(const string & sClassName)
{
return mRegisteredClasses[sClassName];
}
void RegisterClass(const string & sClassName, CAbstractFactory* pConcreteFactory);
private:
map<string, CAbstractFactory* > mRegisteredClasses;
};
// Here I hold the data about all the registered classes. I hold statically one object of this class.
// in this example I register a class CChildClass, which will override the implementation of CBaseClass,
// and a class CFooChildClass which will override CFooBaseClass
class RegistrationData
{
public:
void RegisterAll()
{
mRegisteredClasses.RegisterClass("CBaseClass", & mChildClassFactory);
mRegisteredClasses.RegisterClass("CFooBaseClass", & mFooChildClassFactory);
};
CRegisteredClasses* GetRegisteredClasses(){return &mRegisteredClasses;};
private:
CRegisteredClasses mRegisteredClasses;
CRegisteredClassFactory<CChildClass> mChildClassFactory;
CRegisteredClassFactory<CFooChildClass> mFooChildClassFactory;
};
static RegistrationData StaticRegistrationData;
// and here are the base class and the child class
// in the implementation of CBaseClass::Create I check, whether it should be overridden by another class.
class CBaseClass
{
public:
static CBaseClass* Create()
{
CRegisteredClasses* pRegisteredClasses = StaticRegistrationData.GetRegisteredClasses();
if (pRegisteredClasses->find("CBaseClass"))
{
CRegisteredClassFactory<CBaseClass>* pFac =
dynamic_cast<CRegisteredClassFactory<CBaseClass>* >(pRegisteredClasses->GetFactory("CBaseClass"));
mpInstance = pFac->CreateAndGet();
}
else
{
mpInstance = new CBaseClass;
}
return mpInstance;
}
virtual void Print(){cout << "Base" << endl;};
private:
static CBaseClass* mpInstance;
};
class CChildClass : public CBaseClass
{
public:
void Print(){cout << "Child" << endl;};
private:
};
この実装を使用して、他のクラスからこれを行っている場合:
StaticRegistrationData.RegisterAll();
CBaseClass* b = CBaseClass::Create();
b.Print();
出力に「Child」が含まれることを期待しています。
このデザインどう思いますか?物事を複雑にしすぎたので、もっと簡単にできるでしょうか? また、抽象クラスから継承したテンプレートを作成してもよろしいですか?
dynamic_pointer を使用する必要がありました (それ以外の場合はコンパイルしませんでした) - 何かが間違っているというヒントですか?
ありがとうございました。