我有类Foo
,它有多个构造函数。
class Foo
{
public:
Foo( Param1, Param2 );
Foo( Param1, Param3, Param4 );
Foo( Param1, Param4 );
Foo( Param1, Param2, Param4 );
}
构造函数的实际参数列表很大,我不想直接从其他项目提供对这些构造函数的访问(否则我需要导出这4个构造函数)。我知道避免这种多重构造函数的最佳模式是 Builder Pattern 。但这会给这个类的客户造成混淆,关于哪个param是可选的,哪个param不是。另外每个构造函数都基于参数进行某些验证。因此,在实际使用此对象的任何方法之前,我需要通用的地方进行此类验证。
目前我们正在计划的内容如下:
无变化Foo
类。
定义FooParam
结构
struct FooParam
{
Param1 p1;
Param2 p2;
Param3 p3;
Param4 p4;
}
厂:
Foo* CreateFoo( FooParams& foo )
{
if( foo.Param2 )
{
if( foo.Param4 )
{
return new Foo( foo.param1, foo.param2, foo.param4);
}
else
return new Foo( foo.param1, foo.param2);
}
else if( foo.param4 )
{
if(foo.param3)
return new Foo( foo.param1, foo.param3, foo.param4 );
else
return new Foo( foo.param1, foo.param4 );
}
throw new Exception("Invalid Parameter" );
}
我认为我们可以在第3步做得更好。但现在确定如何?
答案 0 :(得分:1)
如果由于某些原因不想公开构造函数,可以根据模板和完美转发在工厂方法后面隐藏它们:
class Foo {
// defined somewhere
Foo( Param1, Param2 );
Foo( Param1, Param3, Param4 );
Foo( Param1, Param4 );
Foo( Param1, Param2, Param4 );
private:
template<typename... Args>
static auto factory(Args&&... args) {
Foo foo{std::forward<Args>(args)...};
// do whatever you want here
return foo;
}
}
无需在运行时抛出任何东西 如果不存在接受这些参数的构造函数,则会收到编译时错误。
否则,另一种惯用方法是使用named constructors 我直接复制并粘贴上面链接中的示例:
class Game {
public:
static Game createSinglePlayerGame() { return Game(0); }
static Game createMultiPlayerGame() { return Game(1); }
protected:
Game (int game_type);
};
不确定这是否符合您的要求。
那就是说,想想这样做有什么好处:
CreateFoo({ Param1V, Param3V });
更糟糕的是,这个:
FooParams params{ Param1V, Param3V };
CreateFoo(params);
而不是:
new Foo{Param1V, Param3V};
通过引入中级课程,您实际上并没有帮助您班级的用户 他们仍然需要记住特定情况下所需的参数。
答案 1 :(得分:-1)
作为用户,我更喜欢
Foo* CreateFoo(Param1* P1, Param2* P2, Param3* P3, Param4* P4);
为什么我要构建一个struct
来传递一些(可能是NULL)参数?