我想编写适合bean的类。我观察到一种趋势(主要是使用bean)将所需参数从构造函数移动到setter(并在设置初始状态时使用init()
方法)。
这个方法让我很担心,因为我希望我的类在没有bean基础结构的情况下可用,就像Java对象一样。正如我想象的那样,我必须在每个方法断言样式中检查对象的正确状态。
上述快速演示:
class A {
public int x;
public int y;
private int sum;
private boolean initialized = false;
public void init() {
sum = x + y;
initialized = true;
}
private void initCheck() {
if (!initialized) {
throw new IllegalStateException("Uninitialized object.");
}
}
public int getXMulSum() {
initCheck();
return x * sum;
}
public int getYMulSum() {
initCheck();
return y * sum;
}
}
有更好的做法吗?
答案 0 :(得分:3)
鉴于您不想使用框架......
如果一个类在适合使用之前已经初始化,我宁愿使用构造函数。不要被博客和书籍所左右。为此目的,构造者就在那里。使用构造函数也消除了同步代码的任何要求。
我可以看到不使用构造函数的一个原因是,如果有很多初始化代码,并且可能是类外部的依赖项。如果构造函数中存在太多逻辑,那么它可能会使您的应用程序变得脆弱,并且难以从构造函数中的异常中恢复。在这种情况下,您可以选择使用Factory class来处理bean的实例化和初始化。这样,调用代码只接收一个准备就绪并且适合使用的bean 。
要使用的好模式是Builder pattern,其中有一长串构造函数参数。
"我观察到一种倾向(主要是使用bean)将所需参数从构造函数移动到setter"
这种可测试性的主要原因。如果您可以测试bean的功能而无需初始化"昂贵的"依赖关系,而不是在构造函数中没有它们是有益的。话虽如此,我还是会争辩说,如果这是一个问题,你可能在你的bean中有太多的功能,你最好不要分手。正如Single responsibility principle所建议的那样。
答案 1 :(得分:1)
setter比构造函数参数更通用,因为它们允许你处理循环依赖。
如果你没有循环依赖关系,我建议保留构造函数参数,exacly用于枚举依赖项。
但是,如果可能的话,不要将任何逻辑放入构造函数中。正如Brad所说,它使应用程序变得脆弱。构造函数中可能无法使用整个Spring环境。
尝试以允许构造函数简单地记住引用的方式进行设计,以便稍后在真正的方法中使用。如果可以,请避免使用init()方法。