6

私はクラスの署名を持っているとしましょう

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

両方を初期化するにはどうすればよいですか?

4

2 に答える 2

8

クラスの 1 つについては、コンストラクターで参照を提供しませんが、set代わりに -method を使用できます。それらのいずれも以前に存在しない場合、それらの両方を相互に依存して初期化することは困難に思えます。

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の使用など、すべてはオブジェクトの使用方法に依存します。

于 2012-12-06T01:17:38.730 に答える
5

あなたの問題はあまり意味がありません。各クラスで他のクラスを初期化する必要がある場合は、最初にクラスがどのように設計されているかを実際に再考する必要があります。

コンストラクターで指定する代わりに、クラスの1つで他のクラスを作成することを検討してください。例えば ​​:

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また、上記の両方の場合を保証するものでもありません。

クラスはバックリファレンスが適切なものであることを確認する必要があり、どちらのメソッドでもこれを適切に達成することはできません。

この鶏が先か卵が先かという問題を解決するには、ある種のファクトリメソッドまたはサードクラスが必要です。このことを考慮 :

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常にそれを保証されます。


あなたがまだ読んでいるなら、あなたは悟りの道を進んでいます。このクラス設計の結果を理解できれば、循環依存アンチパターンであり、回避する必要があることを理解できます。

しかし、あなたの質問は、私があなたにあなたの問題をきれいでより良い方法で修正するためのより適切な方法を完全に与えるのに十分具体的ではありません。

于 2012-12-06T01:28:05.657 に答える