0

私は「副作用」と言う非常に厄介なことに遭遇しましたが、それは明らかに悪いデザインの問題です。通常のリストを飾るためにGuavaForwardingListパターンを使用しています。私の目的は、maximumSizeに達したときに最も古い要素が追い出されるサイズ制限リストを作成することです(単純なFIFO設計)。既存のコレクションをプロキシまたは複製するつもりはないことに注意してください。しかし、私にはこの非常に厄介な副作用があります:

List<String> originalList = new ArrayList<String>();
int maximumSize = 2;

originalList.add("foo");
originalList.add("bar");

System.out.println(originalList); // [foo, bar]

ListFactory<String> factory = ListFactory.getInstance(String.class);
List<String> decoratedList = factory.newTalendList(originalList, maximumSize);

decoratedList.add("beer");
System.out.println(originalList); // [bar, beer]

originalList.add("ben");
System.out.println(originalList); // [bar, beer, ben] <-- !!!
System.out.println(decoratedList); // [bar, beer, ben] <-- !!!

(注:装飾されたクラスは、add()をオーバーライドして、新しい要素を追加するときにリストの最初の要素を削除します。toString()を含む、オーバーライドされない他のすべてのメソッドは、元のリストに委任されます)

わかりました。元のadd()メソッドを使用して要素を追加すると、最大サイズを超える可能性があります...わかりました。それは避けられないことだと思います(結局のところ、これは設計上間違いではありません)。しかし、これはdecoratedListの設計によるものではありません。

私が見つけた唯一の回避策は次のようなものでした:

List<String> decoratedList = factory.newTalendList(new ArrayList<String>(originalList), maximumSize);

しかし、それは最善の方法ではないようです(そして、それがすべての状況で機能するかどうかはわかりません):私はoriginalListを装飾していませんが、彼女の匿名のクローンです!私は疑問に思っています:おそらく私は自分のデザインを完全に台無しにしたのでしょうか?それを構築するためのより良い方法はありますか?

4

2 に答える 2

9

このパターンが機能する唯一の方法はoriginalList、デコレータを作成した後で二度と参照しない場合です。で何が起こるかを制御することはForwardingListできませんでしたoriginalList。(デコレータはできませんでした。)

全体として、おそらく行うべきことは、完全に新しい装飾リストを返し、元のリストにまったくアクセスできないファクトリメソッドを作成することです。

于 2012-12-13T23:38:17.717 に答える
1

あなたがやろうとしていることはとても奇妙です。元のリストは制約について何も知りません。また、制約されたリストは、彼が元のリストを使用するのは彼だけであると信じています。したがって、装飾されたバージョンを台無しにするような方法で元のリストを使用しないでください。

于 2012-12-13T23:39:32.480 に答える