依赖注入/继承设计模式的构造函数参数太多
Too Many Constructor Args for Dependency Injection/Inheritance Design Pattern
所以我决定使用工厂设计模式和依赖注入。
class ClassA
{
Object *a, *b, *c;
public:
ClassA(Object *a, Object *b, Object *c) :
a(a), b(b), c(c) {}
};
class ClassB : public ClassA
{
Object *d, *e, *f;
public:
ClassB(Object *a, Object *b, Object *c, Object *d, Object *e, Object *f) :
ClassA(a, b, c), d(d), e(e), f(f) {}
};
现在,问题是类B的构造函数参数太多。这是一个单一的继承层示例,但当继承层开始变得更深,并且每个层类都需要构造更多的对象时,顶层的构造函数最终需要太多的参数才能生成!
我知道我可以使用setter而不是构造函数,但还有其他方法吗?
Setter不推荐用于此类操作,因为它们会导致部分构建的对象,非常容易出错。构造需要许多参数的对象的一种常见模式是使用生成器。ClassBBuilder的职责是创建ClassB对象。您将ClassB构造函数设为私有构造函数,并且只允许构造函数使用朋友关系调用它。现在,建设者可以在某种程度上看起来像这个
ClassBBuilder {
public:
ClassBBuilder& setPhoneNumber(const string&);
ClassBBuilder& setName(consg string&);
ClassBBuilder& setSurname(const string&);
ClassB* build();
}
你使用这样的构建器:
ClassB* b = ClassBBuilder().setName('alice').setSurname('Smith').build();
build()方法检查是否设置了所有必需的参数,并返回构造正确的对象或NULL。不可能创建部分构造的对象。您仍然有一个带有许多参数的构造函数,但它是私有的,只能在一个地方调用。客户端看不到。Builder方法也很好地记录了每个参数的含义(当你看到ClassB('o','bar')时,你需要检查构造函数,找出哪个参数是名称,哪个是姓氏)。
这是C++问题之一(如果这可以称为问题的话)。除了尽量减少ctor的参数数量之外,它没有其他解决方案。
其中一种方法是使用props结构,如:
struct PropsA
{
Object *a, *b, *c;
};
class ClassA
{
ClassA(PropsA &props, ... other params);
};
这似乎很明显,但我确实用了好几次。在许多情况下,事实证明某些参数组是相关的。在这种情况下,为它们定义一个结构是有意义的。
我最可怕的噩梦就是使用瘦包装器类。可以直接访问基的方法和数据字段,同时必须复制所有actor。当有10个以上的因素时,创建一个包装器开始成为一个问题。
我认为您所描述的在C++中不是问题——事实上,C++很好地反映了您的设计所表达的依赖关系:
- 要构造
ClassA
类型的对象,需要有三个Object
实例(a
、b
和c
) - 要构造
ClassB
类型的对象,还需要有三个Object
实例(d
、e
和f
) - 每一个类型为CCD_ 11的对象都可以被当作一个类型CCD_
这意味着,对于构造类型为ClassB
的对象,您需要提供实现ClassA
接口所需的三个Object
对象,然后提供另外三个用于实现ClassB
接口。
我相信这里的实际问题是您的设计。你可以考虑不同的方法来解决这个问题:
- 不要让
ClassB
继承ClassA
。可能是也可能不是一个选项,这取决于您是否需要对任一类型的对象进行同质访问(例如,因为您有一个ClassA*
的集合,并且该集合还可以包含指向ClassB
的指针) - 寻找总是一起出现的对象。类似-可能传递给任一构造函数的前两个对象(
a
和b
或d
和e
)代表某种类型的对。也许是对象标识符之类的?在这种情况下,引入一个专门的摘要(读作:type)可能是有益的
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- 在按值调用 (c++) 中转发构造函数参数
- 如何使用 swig 修改类构造函数以保留对其中一个构造函数参数的引用?
- 如何在构造函数参数中初始化"std::set"?
- 何时应在构造函数参数中使用 const C++?
- 使用模板化结构作为构造函数参数
- 使用 lambda 作为构造函数参数是否需要C++ 17?
- 如何使输入文本文件成为构造函数参数?c++
- shared_ptr构造函数参数是否应按值传递
- 是否允许使用初始值设定项列表将const数组引用实例化为构造函数参数
- 复制构造函数参数为0
- 用作成员构造函数参数的函数的求值顺序
- 结构中的默认成员值或默认构造函数参数
- C++将引用成员绑定到构造函数参数
- 如何通过可变参数模板将多个构造函数参数转发到数组初始值设定项列表?
- 模板函数指针参数与构造函数参数
- 如何将 std::string 作为构造函数参数传递,并将其保存的 C 字符串存储在 void 指针中?
- 如何基于构造函数参数模板化类成员函数的代码
- 将派生类构造函数参数传递给受保护的成员
- 如何根据构造函数参数使用超类类型初始化成员变量?