2

新しいJavaプロジェクトでは、可能な限り多くのベストプラクティスを適用しようとしています。私が問題を抱えているのは不変性です。概念を理解し、すでにいくつかの不変クラスを構築しましたが、今では、可変クラスとして実行する方が適切だと思うクラスに到達しました。

主な問題は、場合によってはクラスの可変部分を非表示にして、MVCのビューレイヤーがオブジェクトを直接変更できず、コントローラーを経由する必要があることです。

私はそれを行う2つの方法を考えました:

  1. すべての不変メソッドを含むインターフェース「Thing」(読み取り専用)を作成し、セッターを含むインターフェース「MutableThing」を作成します。

  2. すべてのメソッドを1つのインターフェイスに配置し、Collections.unmodizableList(obj)メソッドのようにオブジェクトをラップして、変更メソッドへのアクセスを制限し、変更メソッドにアクセスするときに例外がスローされるようにします。

私はそれがよりきれいでよりよく設計されていると思うので最初のものを好むでしょう、しかし私はそれに1つの問題があります。「Thing」インターフェースにaddListener(l)とremoveListener(l)があるので、ビューレイヤーはそれ自体をいくつかのモデルオブジェクトのリスナーとして登録できます。しかし、「Thing」インターフェースのこれら2つのメソッドでは、それだけでは意味がなくなります。実際にデータを変更する方法がない場合、インターフェイスにデータの変更を通知するリスナーを登録する機能があるのはなぜですか?これらのメソッドを「MutableThing」インターフェイスに配置することはできますが、ビューレイヤーは「Thing」インターフェイスにしかアクセスできず、リスナーとして登録できませんでした。

これが機能しない理由は、リスナーのせいだけですが、ビューレイヤーは、モデルのリスナーとして自分自身を登録する責任が実際にありますか?コントローラがなんとかして(「MutableThing」にアクセスできる)それを行うことができれば、問題はありませんが、それを実現する方法がわかりません。

あなたは何を提案しますか?

ありがとう!

4

4 に答える 4

3

実際にデータを変更する方法がないのに、データの変更を通知するリスナーを登録する機能がインターフェイスにあるのはなぜですか?

インターフェイスの状態はすべて、次の値を取得できるということです。オブジェクトが不変であることを意味するものではありません。オブジェクトが変更可能な場合、不変オブジェクトにはオブジェクトにはないプロパティ (スレッドセーフ、結果をキャッシュしても安全など) があるため、誰もがそれを認識していることを確認することをお勧めします。あなたのオブジェクトは変更可能です。不変であるふりをしてはいけません。そのため、1 を使用して、Thing インターフェイスで追加/削除を行います。

于 2009-10-20T10:58:18.113 に答える
1

私は変更された最初の試みに行きます。

すべてのゲッターを含むインターフェースによって不変を定義することができます。可変クラスは Immutable インターフェースを実装し、必要なすべての set メソッドをインターフェースで指定せずに含みます。コード内では、Immutable インターフェイスを介してのみインスタンスにアクセスします。実際にクラスを作成または変更する必要があるコード内の場所は、単純にキャストするか、変更する実装を可変クラスと同じパッケージに配置して可視化することにより、これらの可変クラスを (排他的に) 参照します。osgi/eclipse のようなバンドルの概念は、実装を非表示にするなどのサポートを見つけることができるため、ここで役立ちます。

さらに、インスタンスを作成 (および変更) したら、seal() メソッドを使用してインスタンスを封印することもできます。set-method が呼び出されるたびに、インスタンスがシールされていないかどうかを確認します。これは、変更を防ぐのに役立つ場合があります (または大きなチームで作業する場合)。

于 2009-10-20T11:18:23.707 に答える
1

通常、適切なアプローチは、ReadableFoo、ImmutableFoo、MutableFoo の 3 つのクラスやインターフェイスを持つことです。後者の 2 つは最初のものから独立して派生します。つまり、ReadableFoo が必要な場合はどちらも使用できますが、ImmutableFoo が必要な場合は ImmutableFoo しか使用できず、MutableFoo の場合も同様です。ReadableFoo に CloneAsMutable、AsMutable、および AsImmutable のメソッドを含めると役立つ場合があります。CloneAsMutable は常に、オリジナルからコピーされたプロパティを持つ新しい可変オブジェクトを作成します。ReadableFoo で AsMutable および AsImmutable を呼び出すと、元のオブジェクト (目的の型の場合) または元のオブジェクトからデータがコピーされた新しいオブジェクト (そうでない場合) が返されます。

于 2011-06-20T19:17:53.100 に答える
0

私の意見では、あなたが言及した2つの可能性は両方とも、問題を解決するための有効な方法です。最初の方法に関して:私はあなたがインターフェースがミューテーターメソッドを追加するためにインターフェースをMutableThing拡張することを意味すると仮定します。Thing

リスナーのものに関して:これを行うにはもちろんいくつかの方法があります。たとえば、Javaのクラスとインターフェイスを使用してこれをThingandインターフェイスから分離できます(または、自分で作成したものと同様のものです。これらのクラスは、ジェネリックがJavaに追加される前のものであるため、タイプセーフではありません)。MutableThingjava.util.Observablejava.util.Observer

于 2009-10-20T10:57:17.557 に答える