作者热门文章
- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我在代码库的各个地方都有以下层次结构模式:
enum DerivedType {
A, B, C };
class Base {
public:
static Base* Create(DerivedType t);
};
template <DerivedType T>
class Derived : public Base {
};
Create
方法返回类 Derived<A>
的新对象, Derived<B>
, 或 Derived<C>
,取决于它的论点:
Base* Base::Create(DerivedType t) {
switch (t) {
case A: return new Derived<A>;
case B: return new Derived<B>;
case C: return new Derived<C>;
default: return NULL;
}
}
问题是有很多这样的Base -> Derived
层次结构,与 Create()
的实现基本相同到处复制粘贴。是否有一种优雅但易于理解的方法来避免此处重复?
最佳答案
我们可以抽象出工厂细节,并依靠客户端为我们提供枚举到类类型的映射:
template<typename ENUM, typename T>
struct Factory
{
typedef std::map<ENUM, T*(*)()> map_type;
static map_type factoryMapping_;
static T* Create(ENUM c)
{
return factoryMapping_[c]();
}
static void Init(map_type _mapping)
{
factoryMapping_ = _mapping;
}
};
template<typename ENUM, typename T>
typename Factory<ENUM, T>::map_type Factory<ENUM,T>::factoryMapping_;
现在客户的工作是为我们提供创建 Base*
给定一些枚举值的方法。
如果您愿意并且能够使用模板抽象派生类的创建,那么您可以节省大量的输入。
我的意思是,让我们创建一个模板函数来创建一个派生类(没有任何真正的正确性检查):
template<typename Base, typename Derived>
Base* CreateDerived()
{
return new Derived();
}
现在我可以定义一个枚举和关联的类层次结构:
enum ClassType {A, B};
struct Foo
{
virtual void PrintName() const
{
std::cout << "Foo\n";
}
};
typedef Factory<ClassType, Foo> FooFactory ;
struct DerivedOne : public Foo
{
virtual void PrintName() const
{
std::cout << "DerivedOne\n";
}
};
struct DerivedTwo : public Foo
{
virtual void PrintName() const
{
std::cout << "DerivedTwo\n";
}
};
然后像这样使用它:
// set up factory
std::map<ClassType, Foo*(*)()> mapping;
mapping[A] = &CreateDerived<Foo, DerivedOne>;
mapping[B] = &CreateDerived<Foo, DerivedTwo>;
FooFactory::Init(mapping);
// Use the factory
Foo* f = FooFactory::Create(A);
f->PrintName();
当然,这会稍微简化您的问题,即将工厂详细信息移出基类并暂时忽略子级本身已被模板化的情况。取决于在您的域中为每种类型创建良好的 CreateDerived
函数的难度,您最终可能不会节省大量的输入。
编辑:我们可以利用std::map::find 修改我们的Create
函数以返回NULL。 .为了简洁起见,我省略了它。如果您关心性能,那么是的,O(log n) 搜索渐近地比简单的切换慢,但我强烈怀疑这最终会成为热路径。
关于c++ - 带有切换实例化模板的枚举的工厂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37576790/
我是一名优秀的程序员,十分优秀!