我有几种不同的方法可以初始化复杂的对象(注入依赖关系和注入成员所需的设置),都显得合理,但有各种优点和缺点。我给一个具体的例子:从java构造函数调用实例方法是好的还是不好的做法?
final class MyClass {
private final Dependency dependency;
@Inject public MyClass(Dependency dependency) {
this.dependency = dependency;
dependency.addHandler(new Handler() {
@Override void handle(int foo) { MyClass.this.doSomething(foo); }
});
doSomething(0);
}
private void doSomething(int foo) { dependency.doSomethingElse(foo+1); }
}
正如你可以看到,构造函数3样东西,包括调用一个实例方法。我被告知从构造函数中调用实例方法是不安全的,因为它绕过了编译器对未初始化成员的检查。即在设置this.dependency
之前,我可以调用doSomething(0)
,这将会编译但不起作用。什么是重构这个最好的方法?
使
doSomething
静态并显式传入依赖项?在我的实际案例中,我有三个实例方法和三个成员字段,都依赖于另一个,所以这看起来像是很多额外的样板,使所有这三个静态。将
addHandler
和doSomething
转变为@Inject public void init()
方法。虽然与Guice一起使用将是透明的,但它需要任何手动构造才能确保呼叫init()
,否则如果有人忘记该对象,则该对象不会完全起作用。此外,这暴露了更多的API,这两者似乎都是不好的想法。总结嵌套类,以保持相关性,以确保其正常行为不会暴露更多的API:
class DependencyManager { private final Dependency dependency; public DependecyManager(Dependency dependency) { ... } public doSomething(int foo) { ... } } @Inject public MyClass(Dependency dependency) { DependencyManager manager = new DependencyManager(dependency); manager.doSomething(0); }
这会将实例方法的所有构造函数,但产生的阶级额外的一层,当我已经有了内,匿名类(例如那个处理程序)它会变得令人困惑 - 当我尝试这个时,我被告知将DependencyManager
移动到一个单独的文件中,这也是令人厌恶的,因为它现在是多个文件来完成一件事情。
那么,处理这种情况的首选方法是什么?
@Steve:我刚刚删除了第一个“pre”标签,以便代码显示使用颜色编码的语法:) – SyntaxT3rr0r 2010-03-24 22:53:21
酷,不知道它的工作方式。 – Steve 2010-03-25 03:35:49