构造函数需要许多输入参数

时间:2015-02-17 07:38:50

标签: java oop constructor

我的问题涉及java中的构造函数。我已经知道我们应该尽量减少方法的参数数量,包括构造函数。因此,如果我有一个类需要创建很多输入参数,我该怎么做才能做到最好。我应该

A)将它们全部包含在构造函数方法签名中:

示例:

public MyClass(SomeThing A, Vector v, OtherThing B, int number.. etc.){
      // construct
}

..

MyClass c= new MyClass(..);

c.doSomethingWithAllYouGot();

B)我是否可以构造非常少,然后要求对象用户在调用特定方法之前添加内容

public MyClass(SomeThing A){
      // construct
}

..

MyClass c=new MyClass(A);

c.attributeVector(v);
c.connectTo(B);
c.setNumber(n);
// etc.

c.doSomethingWithAllYouGot();

第二个变体看起来更优雅,更干净,但如果不正确使用该类,则会出现更多错误。

如果类的设计有太多输入参数,那么它的设计是否存在问题?

7 个答案:

答案 0 :(得分:2)

如果真的有那么多参数,那么你的班级可能会同时试图做太多事情。以此为例,它可以分解为更小的类。

或者,您可以将构造函数包设为私有,并在同一个包中使用builder来实例化它。

答案 1 :(得分:2)

你建议的方式都有效,但两者都有一些缺点:

  1. 构造函数的参数列表太长,通常很难维护。例如,如果您希望传入5个字符串,则用户几乎不可能在不咨询文档的情况下知道要传递的内容。

  2. 它适用于很多情况,但如果内部状态一致性很重要,或者如果你想使你的对象不可变,那么这可能不是一个好主意。

  3. 还有其他常见的解决方案

    Fluent构建器,因此代码如下所示:

    MyClass c=new MyClassBuilder(A)
                  .withAttributeVector(v);
                  .connectTo(B);
                  .withNumber(n)
                  .create();
    

    因此可以在构建器中隐藏复杂的非直观构造函数调用。

    使用对象作为输入参数

    public MyClass(MyClassConstructParam p){
    }
    
    ..
    MyClassConstructParam p=new MyClassConstructParam();
    p.attributeVector(v);
    p.connectTo(B);
    p.setNumber(n);
    
    MyClass c=new MyClass(p);
    

答案 2 :(得分:0)

我取决于你认为班级基本上需要什么

如果" SomeThing A"这是班级不能没有的东西     - 将其作为主要构造函数中的paremeter包含在内  而" Otherthing B"如果不是基础可以添加为          可以通过其他方法设置的默认值

答案 3 :(得分:0)

在第二种方法中,如果在实例化类之后没有调用setter会怎么样?您的实例将处于一致状态。

有两种方法可以解决这个问题:

  1. 有一个Context类,其中所有参数都是类属性。这样,您将只有一个构造函数参数。

  2. 使用构建器模式。创建一个构建器类。在构建器类的构造函数中,调用类的构造函数,并在构建方法中调用setter。另外,请确保将您的类的构造函数设为私有。

答案 4 :(得分:0)

老实说,有很多构造函数或构造函数有很多参数可能会变得一团糟。

您应该将构建器模式视为@TJ建议,但另一方面,您应该考虑将构造函数中的参数减少到最小集合。该集合可能是必要的参数,也许是在此期间不会改变的数据。

当然,如果所有参数都是必需的,并且必须将它们放入刚刚创建的对象中,那么您应该在构造函数中使用它们。

答案 5 :(得分:0)

来源有效的Java

  

构造函数的问题在于它们不灵活。我们的   示例只有5个参数。但是在上课时想想现实世界   人可能有20个或更多的领域。在这种情况下创建这样的   对象非常冗长。

在现实世界中,类可以具有可选属性以及强制属性

  

在这种情况下,您可能希望创建多个重载   具有不同参数数量的构造函数。避免重复   assignemnt code是使用所谓的伸缩式的常用技术   构造函数,即构造函数调用其他构造函数时的模式。   这种模式很好,但有些过于冗长和困难   修改

现在另一种选择是Bean Pattern,但它有自己的劣势

让我们举一个Simple Bean的例子

class Person {
   private String firstName;
   private String lastName;
   public String getFirstName() {return firstName;}
   public void setFirstName(String firstName) {this.firstName = firstName;}
   public String getLastName() {return lastName;}
   public void setLastName(String lastName) {this.lastName = lastName;}
}

使用

创建实例
Person president = new Person();
p.setFirstName("George");
p.setLastName("Bush");

如你所见:

  1. 初始化确实分为3行。这意味着 当所有3行完成并且在中时,对象处于恒定状态 在此之前不一致的状态。
  2. 该对象确实是可变的:它调用的值可能会被更改 调用setter。
  3. 这就是为什么builder pattern结合了telescoping constructor模式的安全性和JavaBeans pattern的可读性的原因。

答案 6 :(得分:0)

如果对象的变量都与它相关,则它可以根据需要在构造函数中包含尽可能多的变量。

考虑到创建对象时并非所有变量都可以知道/可能为null。因此,不是将空值传递给构造函数,而是在没有参数的情况下在构造函数中实例化。 E.g。

public Student (String firstName, String lastName)
{
   this.firstName = firstName;
   this.lastName = lastName;
   this.grade = 0;
   this.report = "";
}

注意:当您在实例化对象时知道这些值时,当然也会有构造函数。