在 Java 中管理具有多个参数的构造函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/222214/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Managing constructors with many parameters in Java
提问by Steve Armstrong
In some of our projects, there's an class hierarchy that adds more parameters as it goes down the chain. At the bottom, some of the classes can have up to 30 parameters, 28 of which are just being passed into the super constructor.
在我们的一些项目中,有一个类层次结构,当它沿着链向下时会添加更多参数。在底部,一些类最多可以有 30 个参数,其中 28 个刚刚被传递到超级构造函数中。
I'll acknowledge that using automated DI through something like Guice would be nice, but because of some technical reasons, these specific projects are constrained to Java.
我承认通过 Guice 之类的工具使用自动 DI 会很好,但由于某些技术原因,这些特定项目仅限于 Java。
A convention of organizing the arguments alphabetically by type doesn't work because if a type is refactored (the Circle you were passing in for argument 2 is now a Shape) it can suddenly be out of order.
按类型按字母顺序组织参数的约定不起作用,因为如果一个类型被重构(您为参数 2 传入的 Circle 现在是一个 Shape),它可能会突然乱序。
This question might be to specific and fraught with "If that's your problem, you're doing it wrong at a design level" criticisms, but I'm just looking for any viewpoints.
这个问题可能是具体的,并且充满了“如果那是你的问题,你在设计层面做错了”的批评,但我只是在寻找任何观点。
采纳答案by Eli Courtwright
The Builder Design Pattern might help. Consider the following example
Builder Design Pattern 可能会有所帮助。考虑下面的例子
public class StudentBuilder
{
private String _name;
private int _age = 14; // this has a default
private String _motto = ""; // most students don't have one
public StudentBuilder() { }
public Student buildStudent()
{
return new Student(_name, _age, _motto);
}
public StudentBuilder name(String _name)
{
this._name = _name;
return this;
}
public StudentBuilder age(int _age)
{
this._age = _age;
return this;
}
public StudentBuilder motto(String _motto)
{
this._motto = _motto;
return this;
}
}
This lets us write code like
这让我们可以编写类似的代码
Student s1 = new StudentBuilder().name("Eli").buildStudent();
Student s2 = new StudentBuilder()
.name("Spicoli")
.age(16)
.motto("Aloha, Mr Hand")
.buildStudent();
If we leave off a required field (presumably name is required) then we can have the Student constructor throw an exception. And it lets us have default/optional arguments without needing to keep track of any kind of argument order, since any order of those calls will work equally well.
如果我们省略了一个必填字段(大概名称是必需的),那么我们可以让 Student 构造函数抛出异常。它让我们拥有默认/可选参数,而无需跟踪任何类型的参数顺序,因为这些调用的任何顺序都将同样有效。
回答by Aaron Maenpaa
Refactoring to reduce the number of parameters and depth of you inheritance hierarchy is pretty much all I can think of because, nothing is really going to help keep 20-something parameters straight. You're just going to have to every single call while looking at the documentation.
重构以减少参数的数量和继承层次结构的深度几乎是我所能想到的,因为没有什么能真正帮助保持 20 多个参数的清晰。您只需要在查看文档时进行每一次调用。
One thing you could do, is to group some logically grouped parameters into their own higher level object, but that has it's own problems.
您可以做的一件事是将一些逻辑上分组的参数分组到它们自己的更高级别的对象中,但这有其自身的问题。
回答by Mnementh
The best solution is not having too much parameters in the constructor. Only parameters really needed in constructor, are params that are need to correctly initialize the object. You can have constructors with multiple parameters, but also have a constructor with only the minimum parameters. The additional constructors call this simple constructor and after that setters to set the other params. This way you can avoid the chain-problem with more and more params, but also have some convenience-constructors.
最好的解决方案是在构造函数中不要有太多的参数。只有构造函数中真正需要的参数才是正确初始化对象所需的参数。您可以拥有具有多个参数的构造函数,但也可以具有仅具有最少参数的构造函数。额外的构造函数调用这个简单的构造函数,然后调用 setter 来设置其他参数。通过这种方式,您可以避免参数越来越多的连锁问题,但也有一些方便的构造函数。
回答by Guemundur Bjarni
As you are constrained to Java 1.4, if you want DI then Springwould be a very decent option. DI is only helpful in places where the constructor parameters are services or something that does not vary during runtime.
由于您受限于 Java 1.4,如果您想要 DI,那么Spring将是一个非常不错的选择。DI 仅在构造函数参数是服务或在运行时不变的地方有用。
If you have all of those different constructors due to the fact that you want variable options on how to construct an object, you should seriously consider using the Builder pattern.
如果由于需要有关如何构造对象的可变选项而拥有所有这些不同的构造函数,则应该认真考虑使用 Builder 模式。
回答by Michael Myers
What you probably want to do is have a Builder class. Then you would do something like this:
您可能想要做的是拥有一个 Builder 类。然后你会做这样的事情:
MyObject obj = new MyObjectBuilder().setXxx(myXxx)
.setYyy(myYyy)
.setZzz(myZzz)
// ... etc.
.build();
See page 8 and following of this Josh Bloch presentation(PDF), or this review of Effective Java
请参阅此 Josh Bloch 演示文稿(PDF) 的第 8 页及以下内容,或此对 Effective Java 的评论
回答by JeeBee
Can you encapsulate related parameters inside an object?
可以把相关参数封装在一个对象里面吗?
e.g., if parameters are like
例如,如果参数像
MyClass(String house, String street, String town, String postcode, String country, int foo, double bar) {
super(String house, String street, String town, String postcode, String country);
this.foo = foo;
this.bar = bar;
then you could instead have:
那么你可以改为:
MyClass(Address homeAddress, int foo, double bar) {
super(homeAddress);
this.foo = foo;
this.bar = bar;
}
回答by JeeBee
Well, using the builder pattern might be onesolution.
好吧,使用构建器模式可能是一种解决方案。
But once you come to 20 to 30 parameters, I would guess that there is a high relationship between the parameters. So (as suggested) wrapping them into logically sane data-objects probably makes the most sense. This way the data object can already check the validity of constraints between the parameters.
但是一旦你来到 20 到 30 个参数,我猜想参数之间有很高的关系。因此(如建议的那样)将它们包装成逻辑上健全的数据对象可能是最有意义的。通过这种方式,数据对象已经可以检查参数之间约束的有效性。
For all of my projects in the past, once I came to the point to have too many parameters (and that was 8 not 28!) I was able to sanitize the code by creating a better datamodel.
对于我过去的所有项目,一旦我发现参数过多(这是 8 个而不是 28 个!),我就能够通过创建更好的数据模型来清理代码。
回答by Tomas Bjerre
I can really recommend using Immutablesor POJOBuilderwhen using the builder pattern.
在使用构建器模式时,我真的可以推荐使用Immutables或POJOBuilder。