在我们的一些项目中,有一个类层次结构,当它沿着链向下时添加更多的参数。在底部,一些类可以有多达30个参数,其中28个参数刚刚被传递到超级构造函数中。
我承认使用Guice这样的自动化DI会很好,但是由于一些技术上的原因,这些特定的项目被限制在Java上。
按类型按字母顺序组织参数的约定不起作用,因为如果类型被重构(您为参数2传递的圆现在是一个形状),它可能会突然出现无序。
这个问题可能是具体的,充满了"如果这是你的问题,你在设计层面上做的不对"的批评,但我只是在寻找任何观点。
生成器设计模式可能会有所帮助。考虑下面的例子
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();
如果我们去掉了一个必需的字段(假定名称是必需的),那么我们可以让学生构造函数抛出一个异常。它允许我们使用默认/可选参数,而不需要跟踪任何类型的参数顺序,因为这些调用的任何顺序都将同样有效。
当然,对于静态导入,您甚至根本不必"看到"这些"构建者"。例如,可以有静态方法名(字符串名),它返回生成器,学生(student builder)返回学生。因此,学生(姓名("乔")。年龄(15岁)。座右铭("我弄湿了自己");
@Oxbow_Lakes:在您的示例中,哪个类有静态方法名(字符串名)?
从技术上讲,利用学生班来培养一个新的学生是可能的。我在学生班里添加了一些方法,效果很好。这样我就不需要再有一个建设者类了。不过,我不确定这是否可取。是否有理由使用另一个(studentbuilder)类来构建它?
@WVRock:这取决于您的实现。正如我在回答中所说,对学生类本身执行此操作可能会使类处于半初始化状态,例如,如果您有尚未初始化的必选字段。
@Elicourtwright我想这是关于偏好/代码设计的。不是让构造函数抛出异常,而是让buildStudent()方法抛出异常。
我会说,这是一个很好的解决方案
你能在一个对象中封装相关参数吗?
例如,如果参数如下
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;
}
您可能想做的是创建一个生成器类。然后你会这样做:
MyObject obj = new MyObjectBuilder().setXxx(myXxx)
.setYyy(myYyy)
.setZzz(myZzz)
// ... etc.
.build();
请参阅第8页和下面的Josh Bloch演示文稿(PDF),或对有效Java的回顾
好吧,使用构建器模式可能是一种解决方案。
但一旦你达到20到30个参数,我想参数之间有很高的关系。因此(如建议的那样)将它们包装成逻辑上健全的数据对象可能是最有意义的。这样,数据对象就可以检查参数之间约束的有效性。
对于我过去的所有项目,一旦我达到了有太多参数的地步(那是8而不是28!)我可以通过创建更好的数据模型来清理代码。
当您被限制为Java 1.4时,如果您想要DI,那么Spring将是一个非常不错的选择。DI仅在构造函数参数为服务或运行时不变化的地方有用。
如果您有所有这些不同的构造器,因为您需要关于如何构造对象的变量选项,那么您应该认真考虑使用构建器模式。
正如您所提到的,参数主要是服务,所以DI是我需要的。我认为其他几个答案中提到的构建器模式正是我所希望的。
最好的解决方案是在构造函数中没有太多参数。构造函数中真正需要的参数是需要正确初始化对象的参数。可以有多个参数的构造函数,也可以有一个只有最小参数的构造函数。附加的构造函数调用这个简单的构造函数,并在该setter之后设置其他参数。这样可以避免使用越来越多的参数时出现链问题,但也有一些方便的构造函数。
我真的可以推荐在使用构建器模式时使用不可变项或pojobuilder。
重构以减少参数的数量和继承层次结构的深度几乎是我能想到的,因为没有什么能真正帮助保持20多个参数的正态性。在查看文档时,您只需要每次打电话。
您可以做的一件事是,将一些逻辑分组的参数分组到它们自己的更高级别对象中,但这有它自己的问题。