【发布时间】:2012-12-06 10:03:13
【问题描述】:
假设我有类签名
Class1(Class2 c);
Class2(Class1 c);
如何初始化两者?
【问题讨论】:
-
那些是构造函数,而不是类签名。这实际上看起来像是一个架构问题。
标签: java class dependencies
假设我有类签名
Class1(Class2 c);
Class2(Class1 c);
如何初始化两者?
【问题讨论】:
标签: java class dependencies
对于其中一个类,您无需在构造函数中提供引用,但您可以改用set-方法。当它们以前都不存在时初始化它们相互依赖似乎很困难。
class Foo {
private Bar bar;
public Foo(Bar bar) {
this.bar = bar;
}
}
class Bar {
private Foo foo;
setFoo(Foo foo) {
this.foo = foo;
}
}
Bar bar = new Bar();
Foo foo = new Foo(bar);
bar.setFoo(foo);
另请注意,可能有更好的解决方案。比如使用Observer-pattern,这完全取决于你打算如何使用你的对象。
【讨论】:
你的问题没有多大意义。如果每个类都需要另一个类来初始化,那么您真的必须首先重新考虑您的类是如何设计的。
您可能会考虑让其中一个类自己创建另一个类,而不必在构造函数中指定它。例如:
class Class1 {
private Class2 c2;
public Class1() {
this.c2 = new Class2(this);
}
}
class Class2 {
private Class1 c1;
public Class2(Class1 c) {
this.c1 = c;
}
}
或者创建设置器并允许它们在“未初始化”状态下创建(如果设置不正确,可能会引发异常)。例如:
class Class1 {
private Class2 c2;
public void setClass2(Class2 c) {
this.c2 = c;
}
public void doSomething() {
if (null == c2) throw new IllegalStateException();
// ...
}
}
class Class2 {
private Class1 c1;
public void setClass1(Class1 c) {
this.c1 = c;
}
public void doSomething() {
if (null == c1) throw new IllegalStateException();
// ...
}
}
// somewhere else....
Class1 c1 = new Class1();
Class2 c2 = new Class2();
c1.setClass2(c2);
c2.setClass1(c1);
另外,如果每个实例都需要相互链接,您应该检查它们是否确实由正确的对象拥有,否则您可能会创建错误的引用......这正是它是一个糟糕设计的原因首先。考虑一下:
Class2 c2 = new Class2(new Class1());
你可能认为这是一个聪明的结构,但是c2.getClass1().getClass2() != c2。
在上述两种情况下,它都不保证c1.getClass2() == c2 && c2.getClass1() == c1。
你的类应该检查反向引用是正确的,你不能用任何一种方法正确地实现这一点!
要解决这个先有鸡还是先有蛋的问题,您需要某种工厂方法或third class。考虑一下:
abstract class Class1 {
public abstract Class2 getClass2();
}
abstract class Class2 {
public abstract Class1 getClass1();
}
public Class3 {
private Class1 c1;
private Class2 c2;
public Class3() {
c1 = new Class1_Impl();
c2 = new Class2_Impl();
}
public Class1 getClass1() { return c1; }
public Class2 getClass2() { return c2; }
private class Class1_Impl extends Class1 {
public Class1 getClass2() { return c2; }
}
private class Class2_Impl extends Class2 {
public Class1 getClass1() { return c1; }
}
}
// and later on...
Class3 c3 = new Class3();
Class1 c1 = c3.getClass1();
Class2 c2 = c3.getClass2();
有了这个,您就可以保证c1.getClass2() == c2 && c2.getClass1() == c1 始终如此。
如果你还在读书,那么你就在启蒙的轨道上。如果你能看到这种类设计的后果是什么,那么你就会明白circular dependency是一个anti-pattern,应该避免。
但是,您的问题不够具体,我无法完全为您提供更正确的方法来以干净和更好的方式解决您的问题。
【讨论】: