如何在Java中初始化依赖于彼此的类?

时间:2012-12-06 01:14:04

标签: java class dependencies

说我有班级签名

Class1(Class2 c);
Class2(Class1 c);

如何初始化两者?

2 个答案:

答案 0 :(得分:7)

对于其中一个类,您不在构造函数中提供引用,但您可以使用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,这一切都取决于您计划如何使用对象。

答案 1 :(得分:5)

你的问题没有多大意义。如果每个类都需要另一个类进行初始化,那么您必须首先重新考虑类的设计方式。

您可能会考虑让其中一个类本身创建另一个类,而不必在构造函数中指定它。例如:

class Class1 {
    private Class2 c2;
    public Class1() {
        this.c2 = new Class2(this);
    }
}

class Class2 {
    private Class1 c1;
    public Class2(Class1 c) {
        this.c1 = c;
    }
}

或者创建setter并允许它们以“未初始化”状态创建(如果设置不正确,可能会抛出异常)。例如:

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 dependencyanti-pattern的方式,应该避免使用。

但是,您的问题不够具体,我无法全面为您提供更合适的方式以更干净,更好的方式解决您的问题。