1

私は、双方向の関連付けを処理する一般的な方法と、手動で記述されたJavaコードで逆更新を処理する方法を探していました。

私が何について話しているのかわからない人のために、ここに例があります。その下には、(満足できない)ソリューションの現在の結果があります。

public class A {
    public B getB();
    public void setB(B b);
}

public class B {
    public List<A> getAs();
}

これで、関連付けのいずれかの端を更新するときに、一貫性を維持するために、もう一方の端も更新する必要があります。毎回手動で

a.setB(b);
b.getA().add(a);

または、一致するコードをsetter / getterに配置し、カスタムリスト実装を使用します。

依存関係が利用できなくなった、古くて保守されていないプロジェクトを見つけました(https://e-nspire-gemini.dev.java.net/)。必要なコードを自動的に挿入するために使用される注釈を使用して、問題に対処します。

ジェミニの一般的で目立たない方法でこれを処理する別のフレームワークを知っている人はいますか?

チャオ、エルマー

4

4 に答える 4

5

googleコレクション(googleの内部コードから)-http://code.google.com/p/google-collections/はJava Genericsと互換性があります(互換性があるだけでなく、genericsを非常によく使用します)

クラスBiMap- http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?http: //google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/ collect / package-summary.html は、双方向の関連付けを可能にします。

これらのクラスのいくつかは、JDK7に組み込まれることが期待されています。

于 2008-10-04T00:47:44.253 に答える
0

意味をなすために、これらの呼び出しはピアになります。一貫性を保つために、(友人が不在の場合の) パッケージ プライベート メカニズムを提案します。

public final class A {
    private B b;
    public B getB() {
        return b;
    }
    public void setB(final B b) {
        if (b == this.b) {
            // Important!!
            return;
        }
        // Be a member of both Bs (hence check in getAs).
        if (b != null) {
            b.addA(this);
        }
        // Atomic commit to change.
        this.b = b;
        // Remove from old B.
        if (this.b != null) {
            this.b.removeA(this);
        }
    }
}

public final class B {
    private final List<A> as;
    /* pp */ void addA(A a) {
        if (a == null) {
            throw new NullPointerException();
        }
        // LinkedHashSet may be better under more demanding usage patterns.
        if (!as.contains(a)) {
            as.add(a);
        }
    }
    /* pp */ void removeA(A a) {
        if (a == null) {
            throw new NullPointerException();
        }
        as.removeA(a);
    }
    public List<A> getAs() {
        // Copy only those that really are associated with us.
        List<A> copy = new ArrayList<A>(as.size());
        for (A a : as) {
            if (a.getB() == this) {
                copy.add(a);
            }
        }
        return Collection.unmodifiableList(copy);
    }
}

(免責事項: テストもコンパイルもされていません。)

ほとんどの例外は安全です (例外の場合はリークする可能性があります)。スレッド セーフ、多対多、パフォーマンス、ライブラリ化などは、関心のある読者への演習として残されています。

于 2008-10-04T13:56:31.913 に答える
0

セッターを抽象化しない限り、何らかのイベント通知メカニズムを提供する必要があります。オブジェクトが JavaBeans の場合は、PropertyChangeSupport の使用とプロパティ変更イベントの起動を検討しています。

それを行う場合 (または変更を検出するための他のメカニズムがある場合)、Glazed Lists はObservableElementListを提供します。これを使用して、リストの最後から関連付けの同期を簡単に処理できます (つまり、A を List< A> に追加すると、a.setB( が自動的に呼び出されます)。 b)))。もう一方の方向は、プロパティ変更監視 (または同等のもの) を使用して簡単に処理できます。

これは一般的な解決策ではないことは承知していますが、簡単な基​​盤になるようです。

このようなものには、B クラスでの特別なリストの実装が必要になることに注意してください。一般的なケース (つまり、ArrayList などを使用) で処理できる AOP タイプのソリューションにほかなりません。

また、あなたが達成しようとしているのは、データ バインディングの聖杯のようなものであることも指摘しておく必要があります。フィールド レベルでバインドするための適切な実装 (ゲッターやセッターなど) がいくつかあります (例については、JGoodies バインディングと JSR 295 を参照してください)。また、リスト タイプ バインディングの非常に優れた実装も 1 つあります (上記の Glazed Lists)。私たちは、ほとんどすべてのアプリケーションで両方の手法を相互に連携させて使用していますが、あなたが求めているほど抽象的にしようとしたことはありません.

私がこれを設計しているとしたら、次のようになります。

AssociationBuilder.createAssociation(A a, Connector< A> ca, B b,  Connector< B> cb, Synchronizer< A,B> sync)

コネクタは、さまざまな変更通知の種類に対して単一のインターフェイスを可能にするインターフェイスです。Synchronizer は、いずれかのオブジェクトが変更されるたびに、両方のオブジェクトが同期されていることを確認するために呼び出されるインターフェイスです。

sync(ChangeInfo info, A a, B b) // make sure that b reflects current state of a and vice-versa.  

ChangeInfo は、どのメンバーが変更されたか、および実際の変更内容に関するデータを提供します。私たちです。このジェネリックを本当に維持しようとしている場合は、これの実装をフレームワークユーザーにパントする必要があります。

上記が整っていれば、さまざまなバインディング基準を満たす、事前定義された多数のコネクターとシンクロナイザーを持つことができます。

興味深いことに、上記のメソッド シグネチャは、JSR 295 の createAutoBinding() メソッド呼び出しと非常によく似ています。プロパティ オブジェクトはコネクタと同等です。JSR 295 には Synchronizer がありません (代わりに、ENUM として指定されたバインディング戦略があります。さらに、JSR 295 はプロパティ -> プロパティ バインディングでのみ機能し、あるオブジェクトのフィールド値を別のオブジェクトのそのオブジェクトのリスト メンバーシップにバインドしようとします。彼らのテーブルにもありません)。

于 2008-10-04T04:50:20.160 に答える
0

すべての提案に感謝します。しかし、私が探していたものに近づくものはありませんでした。おそらく、質問を間違った方法で定式化しました。

私はジェミニの代替品を探していたので、際限のないチェックと特別なリストの実装でコードを汚染することなく、目立たない方法でこれを処理する方法を探していました。もちろん、Kevin が提案したように、これには AOP ベースのアプローチが必要です。

もう少し調べてみると、すべてのソースとソースとの依存関係を含むジェミニのパッケージが cnet で見つかりました。依存関係のソースが見つからないことが、私がそれを使用するのを妨げた唯一の懸念事項でした。現在、すべてのソースが利用可能であるため、バグを修正できます。誰かがこれを探している場合: http://www.download.com/Gemini/3000-2413_4-10440077.html

于 2008-10-05T20:50:55.993 に答える