我的问题涉及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();
第二个变体看起来更优雅,更干净,但如果不正确使用该类,则会出现更多错误。
如果类的设计有太多输入参数,那么它的设计是否存在问题?
答案 0 :(得分:2)
如果真的有那么多参数,那么你的班级可能会同时试图做太多事情。以此为例,它可以分解为更小的类。
或者,您可以将构造函数包设为私有,并在同一个包中使用builder来实例化它。
答案 1 :(得分:2)
你建议的方式都有效,但两者都有一些缺点:
构造函数的参数列表太长,通常很难维护。例如,如果您希望传入5个字符串,则用户几乎不可能在不咨询文档的情况下知道要传递的内容。
它适用于很多情况,但如果内部状态一致性很重要,或者如果你想使你的对象不可变,那么这可能不是一个好主意。
还有其他常见的解决方案
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会怎么样?您的实例将处于一致状态。
有两种方法可以解决这个问题:
有一个Context类,其中所有参数都是类属性。这样,您将只有一个构造函数参数。
使用构建器模式。创建一个构建器类。在构建器类的构造函数中,调用类的构造函数,并在构建方法中调用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");
如你所见:
这就是为什么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 = "";
}
注意:当您在实例化对象时知道这些值时,当然也会有构造函数。