OOP初始化策略

时间:2012-01-02 13:24:48

标签: oop constructor

我经常需要在这两个对象设计策略之间做出决定:

  1. 完全初始化并在构建后即可使用的对象。构造函数通常需要复杂的参数列表,因此对象初始化是不重要的。将它作为成员变量的所有对象也需要非常重要的构造函数。这可能会导致代码的复杂性集中在对象构造函数上,这通常会使代码难以遵循。
  2. 具有默认构造函数的对象。对象变量通过setter methods单独设置。这种方法的缺点是大多数方法需要检查对象是否已完全初始化,从而使代码复杂化。
  3. 您的个人偏好是什么?您如何决定何时使用其中一种?

4 个答案:

答案 0 :(得分:2)

在我看来,如果构造函数变得过于膨胀,那么就应该将对象拆分为更多不同的较小对象。在极少数情况下这可能是不可能的,但在大多数情况下可以这样做。

答案 1 :(得分:2)

如果一个构造函数需要很多参数 - 你称之为非平凡的对象初始化 - 并且你不想将你的类分成更小的类,那么另一种方法是将参数放入Parameter Object和然后只将该对象传递给构造函数。

其次,我相信你应该区分......

  • 如果对象应该执行其工作,则绝对必须设置的对象属性,并且没有合理的默认值。应通过构造函数参数初始化这些属性。

  • 用户可以选择或覆盖的对象属性。虽然您可能在构造函数中初始化此类属性,但您不必为它们分配单独的构造函数参数。相反,您可以为它们分配一个合理的默认值,仍然可以由用户通过setter方法覆盖。

还有第一种类型的属性(必须绝对具有用户提供的值)的替代方法:通过覆盖派生类中的抽象getter提供的属性:

abstract class ComplicatedFoo {
    protected abstract T getSomeDependency(); // replaces required ctor parameter
}

P.S。:本书"Dependency Injection" by Dhanji R. Prasanna (Manning Publications)概述了如何初始化对象的各种方法。

答案 2 :(得分:2)

都不是。 巨大的参数列表表明该对象做得太多。在对象具有有效且有用的输出之前需要设置的许多属性表明它做得太多。 因此,就我而言,这两种方法都不是解决方案。

有很多方法可以解决这些问题,但在特定情况之外,唯一的规则是“它需要做”。

聚合到其他对象,“控制器”类,各种通信器模式。是一些类别的第一类对象,有些可以隐藏在实现中。

我不接受你提出的两个选项是唯一的选项,除了可能从实用的角度来看代码的出现。我被迫选择哪一个,只取决于构造函数对代码所需的不同参数的调用次数,以及确认所有属性设置需要多少验证,以及可能对单元测试的影响,因为物体乱七八糟是笨重或有限的。

答案 3 :(得分:-1)

在构造函数中初始化所有变量总是很好,但是默认值。如果很难获得变量的值(例如,您必须在某处调用某个函数来获取该值),您可以将该值设置为无效值,然后再设置正确的值。

使构造函数如此复杂并不是一个好主意,因为你不能在构造函数中返回错误(我不知道是否可以在构造函数中抛出异常,因为我特别不喜欢在任何地方实现异常)。此外,您无法在那里调用虚拟功能,等等。

当类的构造很复杂时,我喜欢的方法是创建一个“init”函数。然后我可以做类似的事情:

Person::Person()
{
    age = -1;
    ...
}

int Person::Init()
{
    age = functionThatReturnsTheAgeFromSomeDB();
    if (age == -1 )
    {
        return DB_ERROR;
    }
    ...
}

等等。