java中最终字段初始化的oop问题:使用多个构造函数避免代码重复
我有一个课程,有一些私人的最终字段:
public class ClassA {
private final Object field1;
private final Object field2;
...
}
该类有几个不同的构造函数,具有各种参数:
public ClassA(Object arg1, Object arg2);
public ClassA(int arg1, String arg2, boolean arg3);
这些构造函数计算要放入最终字段的值
理想情况下,我想做这样的事情:
public ClassA(Object arg1, Object arg2) {
... // error check params
Object value1 = ... // calculate value 1 based on args
Object value2 = ... // calculate value 2 based on args
init(value1, value2);
}
public ClassA(int arg1, String arg2, boolean arg3) {
... // error check params
Object value1 = ... // calculate value 1 based on args
Object value2 = ... // calculate value 2 based on args
init(value1, value2);
}
private void init(Object arg1, Object arg2) {
... // error checks on combination of calculated arg1 and arg2 values
... // in reality there are more than 2 args, and this logic is fairly complex
field1 = arg1;
field2 = arg2;
... // other common initialization code, depends on field1 and field2
}
为了重用分配和通用初始化代码。但是,由于字段是最终字段,因此只能在构造函数调用中分配它们
在这种情况下,无法避免使用公共构造函数生成对象,因此任何类型的工厂方法都是不可能的。最好将arg1和arg2值的组合错误检查与它们对ClassA字段的赋值保持在同一块中。否则,我会将init()
拆分为两个函数,一个预分配final字段,一个后分配final字段,并使我的构造函数看起来像:
public ClassA(int arg1, String arg2, boolean arg3) {
... // error check params
Object value1 = ... // calculate value 1 based on args
Object value2 = ... // calculate value 2 based on args
preinit(value1, value2); // error checks combination of values
field1 = value1;
field2 = value2;
postinit(); // other common initialization code
}
建议?有没有办法避免这种情况,或者我被困在分割init()
函数的过程中了
# 1 楼答案
为什么不在静态工厂方法中创建对象
value1
和value2
?然后,您可以使用不同的工厂方法替换当前的构造函数,并使用单个(私有)构造函数执行init
中现在所做的操作:# 2 楼答案
不知道这是否是一个选项,但您可以使用依赖项注入,也就是说,您可以创建字段在其他地方引用的对象,然后将它们传递到构造函数中。这使你的类更容易测试,也更灵活
这样,你就可以:
# 3 楼答案
首先,我会尝试查看生成器模式,但如果您坚持将其作为构造函数,并且字段应该是最终字段,请使用私有构造函数:
# 4 楼答案
您可以将所有内容下推到一个2参数构造函数,以便它是唯一一个实际初始化最终字段并进行验证的构造函数
例如
如果你不想直接调用两个对象的版本(例如,假设你想在赋值之前进行预验证),那么就声明一个“伪”参数。这感觉有点错误,但如果你想让公共构造函数和私有构造函数在语义上具有相同的参数(它们必须在语法上是不同的),这确实是唯一的选择
# 5 楼答案
您可以将构造函数链接在一起,而不是使用单独的
init
方法。因此,计算field
和field2
,然后调用初始化它们的构造函数。基本上,将init
替换为:当然,只有一个构造函数的参数为2
Objects