6

所以我决定使用工厂设计模式和依赖注入。

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) {}
};

现在,问题是 classB 的构造函数参数太多。这是一个单继承层的例子,但是当继承层开始变深时,当每个层类需要构造更多的对象时,顶层的构造函数最终需要太多的参数才能生成!

我知道我可以使用 setter 而不是构造函数,但是还有其他方法吗?

4

3 回答 3

6

不建议将 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。不可能创建部分构造的对象。您仍然有一个带有许多参数的构造函数,但它是私有的并且只在一个地方调用。客户不会看到它。构建器方法还很好地记录了每个参数的含义(当您看到 ClassB('foo', 'bar') 时,您需要检查构造器以确定哪个参数是名称,哪个是姓氏)。

于 2012-09-06T07:37:22.420 回答
1

我认为您所描述的在 C++ 中不是问题 - 事实上,C++ 很好地反映了您的设计所表达的依赖关系:

  1. 要构造 类型的对象ClassA,您需要具有三个Object实例(abc
  2. 要构造 类型的对象ClassB,还需要三个Object实例(def
  3. 每个类型的对象ClassB都可以被视为一个类型的对象ClassA

这意味着要构造一个类型的对象,ClassB您需要提供三个Object实现ClassA接口所需的对象,然后再提供三个用于实现ClassB接口的对象。

我相信这里的实际问题是您的设计。您可以考虑使用不同的方法来解决此问题:

  1. 不要让ClassB继承ClassA。可能是也可能不是一个选项,具体取决于您是否需要对任一类型的对象进行同质访问(例如,因为您有一个集合,ClassA*并且该集合也可能包含指向 的指针ClassB)。
  2. 寻找总是一起出现的物体。像 - 也许传递给任一构造函数(aandbdand e)的前两个对象代表某种对。也许是对象标识符之类的?在这种情况下,为此引入一个专用的抽象(阅读:类型)可能是有益的。
于 2012-09-06T07:50:49.097 回答
1

这是 C++ 问题之一(如果这可以称为问题)。除了试图保持 ctor 的参数数量最少之外,它没有其他解决方案。

其中一种方法是使用 props 结构,例如:

struct PropsA
{
    Object *a, *b, *c;
};

class ClassA
{
    ClassA(PropsA &props, ... other params);
};

这似乎很明显,但我确实使用过几次。在许多情况下,事实证明某些参数组是相关的。在这种情况下,为它们定义一个结构是有意义的。

我最糟糕的噩梦是瘦包装类。可以直接访问基础的方法和数据字段,而必须复制所有 ctor。当有 10 多个 ctor 时,创建包装器开始成为问题。

于 2012-09-04T17:37:22.070 回答