用Java中的许多参数pipe理构造函数

在我们的一些项目中,有一个类层次结构可以在链条上添加更多的参数。 在底部,一些类可以有多达30个参数,其中28个只是传递给超级构造函数。

我会承认,通过像Guice这样的自动化DI将会很好,但是由于某些技术原因,这些特定的项目被限制在Java。

按types按字母顺序组织参数的惯例不起作用,因为如果某个types被重构(您为参数2传入的圆现在是一个形状),它可能会突然失灵。

这个问题可能是特定的,充满“如果这是你的问题,你在devise层面上做错了”的批评,但我只是在寻找任何观点。

Builderdevise模式可能会有所帮助。 考虑下面的例子

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

这让我们编写像

 Student s1 = new StudentBuilder().name("Eli").buildStudent(); Student s2 = new StudentBuilder() .name("Spicoli") .age(16) .motto("Aloha, Mr Hand") .buildStudent(); 

如果我们放弃一个必填字段(大概需要name),那么我们可以让Student构造函数抛出一个exception。 它可以让我们有默认的/可选的参数,而不需要跟踪任何types的参数顺序,因为这些调用的任何顺序都可以很好地工作。

你能封装一个对象的相关参数吗?

例如,如果参数是类似的

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;
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; 

那么你可以有:

MyClass(Address homeAddress, int foo, double bar) { super(homeAddress); this.foo = foo; this.bar = bar; }
MyClass(Address homeAddress, int foo, double bar) { super(homeAddress); this.foo = foo; this.bar = bar; } 

你可能想要做的是有一个生成器类。 那么你会做这样的事情:

 MyObject obj = new MyObjectBuilder().setXxx(myXxx) .setYyy(myYyy) .setZzz(myZzz) // ... etc. .build(); 

请参阅此Josh Bloch演示文稿 (PDF)的第8页和以下内容,或对Effective Java的评论

那么,使用构build器模式可能是一个解决scheme。

但是一旦你达到了20到30个参数,我猜测参数之间有很高的关系。 所以(按照build议)把它们包装成逻辑上合理的数据对象可能是最有意义的。 这样数据对象就可以检查参数之间约束的有效性了。

对于我以前的所有项目来说,一旦我发现有太多的参数(那8个不是28!),我就可以通过创build一个更好的数据模型来清理代码。

正如你被约束到Java 1.4,如果你想DI,那么Spring将是一个非常体面的select。 DI仅在构造函数参数是服务的地方或在运行时不变的地方有用。

如果你有所有这些不同的构造函数,由于你想要如何构造一个对象的variables选项,你应该认真考虑使用Builder模式。

最好的解决scheme是在构造函数中没有太多的参数。 只有在构造函数中真正需要的参数是需要正确初始化对象的参数。 你可以有多个参数的构造函数,但也有一个只有最小参数的构造函数。 额外的构造函数调用这个简单的构造函数,然后设置其他参数。 这样可以避免带有越来越多的参数的链式问题,而且还有一些方便的构造函数。

在使用构build器模式时,我真的可以推荐使用Immutable或POJOBuilder 。

重构可以减less参数和深度,这是我所能想到的,因为没有什么能真正帮助保持20个参数。 在查看文档时,您只需要每一个电话。

你可以做的一件事是将一些逻辑分组的参数分组到自己的高层对象中,但是这有它自己的问题。