删除具有相似工厂的重复代码 类
Remove duplicate code with similar factory classes
我有这个代码:
struct Foo1 {}
struct Foo1Helper {} // generated
struct Foo2 {}
struct Foo2Helper {} // generated
struct Foo1Factory {
Foo1* Create(){
return connect();
}
protected:
Foo1 *connect();
}
// cpp file (important because i don't want to have Foo1Helper in .h file)
Foo1* Foo1Factory::connect(){
return Foo1Helper::doSmth();
}
struct Foo2Factory {
Foo2* Create(){
return connect();
}
protected:
Foo2 *connect();
}
// cpp file (important because i don't want to have Foo2Helper in .h file)
Foo2* Foo2Factory::connect(){
return Foo2Helper::doSmth();
}
我有两个 classes Foo1 和 Foo2,它们都是在 Foo1Helper 和 Foo2Helper classes 的帮助下通过工厂 class 创建的。
想法是只用一个工厂class因为有很多重复代码,唯一的区别是在连接函数中调用的辅助函数。
注意:我想从头文件中隐藏 Helper classes,因此连接函数必须在 .cpp 文件中实现。
如果您可以忍受定义一些别名,则可以拥有一个工厂;如果您可以接受一些显式模板实例化,则可以将您的助手 类 隐藏在 cpp 中。而且我不明白你为什么不这样做。
在下文中,我假设您的工厂方法是静态的。如果不是,可以很容易地用 pimpl 惯用语进行改编。
头文件
struct Foo1 { /* implementation */ };
struct Foo1Helper; // just declaration
struct Foo2 { /* implementation */ };
struct Foo2Helper; // just declaration
// a little helper
template <class Foo_main, class Helper>
struct Foo_trait
{
using Foo = Foo_main;
using FooHelper = Helper;
};
// this section can be easily generated
// if you have a lot of classes and feel particularly lazy
using Foo1_trait = Foo_trait<Foo1, Foo1Helper>;
using Foo2_trait = Foo_trait<Foo2, Foo2Helper>;
// just one Factory class
// no implementation exposed to the header
template <class Foo_trait>
struct FooFactory
{
using Foo = typename Foo_trait::Foo;
using FooHelper = typename Foo_trait::FooHelper;
static auto Create() -> Foo*;
};
源文件
struct Foo1Helper
{
static Foo1* doSmth()
{
static Foo1 f;
return &f;
}
};
struct Foo2Helper
{
static Foo2* doSmth()
{
static Foo2 f;
return &f;
}
};
template <class Foo_trait>
auto FooFactory<Foo_trait>::Create() -> Foo*
{
return FooHelper::doSmth();
}
// explicit template instantiation
// very important. Without this you get linker erorrs
// again very easy to generate
template struct FooFactory<Foo1_trait>;
template struct FooFactory<Foo2_trait>;
用法
Foo1 f1 = FooFactory<Foo1_trait>::Create();
Foo2 f2 = FooFactory<Foo2_trait>::Create();
如果您可以控制 FooN
,那么您可以完全跳过 Foo_trait
,并在 FooN
中定义一个别名。例如
struct Foo1
{
using Helper = Foo1Helper;
};
我有这个代码:
struct Foo1 {}
struct Foo1Helper {} // generated
struct Foo2 {}
struct Foo2Helper {} // generated
struct Foo1Factory {
Foo1* Create(){
return connect();
}
protected:
Foo1 *connect();
}
// cpp file (important because i don't want to have Foo1Helper in .h file)
Foo1* Foo1Factory::connect(){
return Foo1Helper::doSmth();
}
struct Foo2Factory {
Foo2* Create(){
return connect();
}
protected:
Foo2 *connect();
}
// cpp file (important because i don't want to have Foo2Helper in .h file)
Foo2* Foo2Factory::connect(){
return Foo2Helper::doSmth();
}
我有两个 classes Foo1 和 Foo2,它们都是在 Foo1Helper 和 Foo2Helper classes 的帮助下通过工厂 class 创建的。
想法是只用一个工厂class因为有很多重复代码,唯一的区别是在连接函数中调用的辅助函数。
注意:我想从头文件中隐藏 Helper classes,因此连接函数必须在 .cpp 文件中实现。
如果您可以忍受定义一些别名,则可以拥有一个工厂;如果您可以接受一些显式模板实例化,则可以将您的助手 类 隐藏在 cpp 中。而且我不明白你为什么不这样做。
在下文中,我假设您的工厂方法是静态的。如果不是,可以很容易地用 pimpl 惯用语进行改编。
头文件
struct Foo1 { /* implementation */ };
struct Foo1Helper; // just declaration
struct Foo2 { /* implementation */ };
struct Foo2Helper; // just declaration
// a little helper
template <class Foo_main, class Helper>
struct Foo_trait
{
using Foo = Foo_main;
using FooHelper = Helper;
};
// this section can be easily generated
// if you have a lot of classes and feel particularly lazy
using Foo1_trait = Foo_trait<Foo1, Foo1Helper>;
using Foo2_trait = Foo_trait<Foo2, Foo2Helper>;
// just one Factory class
// no implementation exposed to the header
template <class Foo_trait>
struct FooFactory
{
using Foo = typename Foo_trait::Foo;
using FooHelper = typename Foo_trait::FooHelper;
static auto Create() -> Foo*;
};
源文件
struct Foo1Helper
{
static Foo1* doSmth()
{
static Foo1 f;
return &f;
}
};
struct Foo2Helper
{
static Foo2* doSmth()
{
static Foo2 f;
return &f;
}
};
template <class Foo_trait>
auto FooFactory<Foo_trait>::Create() -> Foo*
{
return FooHelper::doSmth();
}
// explicit template instantiation
// very important. Without this you get linker erorrs
// again very easy to generate
template struct FooFactory<Foo1_trait>;
template struct FooFactory<Foo2_trait>;
用法
Foo1 f1 = FooFactory<Foo1_trait>::Create();
Foo2 f2 = FooFactory<Foo2_trait>::Create();
如果您可以控制 FooN
,那么您可以完全跳过 Foo_trait
,并在 FooN
中定义一个别名。例如
struct Foo1
{
using Helper = Foo1Helper;
};