2012-12-13 29 views
0

我遇到了一個非常討厭的問題,我會說'副作用',但這顯然是一個糟糕的設計問題。我正在使用Guava ForwardingList模式來裝飾常規列表。我的目的是構建一個限制大小的列表,其中最大元素滿足時(最簡單的FIFO設計),最老的元素被踢出。請注意,我不會代理或克隆現有的集合。但是我有這個很討厭的副作用:裝飾使用番石榴的集合的意外行爲ForwardingList

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] <-- !!! 

(注:我飾類重寫添加()在添加一個新的刪除列表的第一個元素的所有其他非重寫的方法,包括的toString( ),被授予原來的列表)

好吧,你可能會看到如果我使用原始的add()方法添加一個元素,我可以超過最大尺寸...好吧,我想這是不可避免的(並沒有錯畢竟設計)。但這並不是真正爲decorationList設計的。

我發現的唯一的解決方法是這樣的:

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

,但它不似乎是最好的方式(我不知道它在每一個circumnstances工作):我不是裝飾 originalList,但她的匿名克隆!我想知道:也許我完全搞亂了我的設計?有沒有更好的方法來建立它?

回答

9

這種模式的工作方式唯一的方法是如果你在創建裝飾器後再也不會引用originalListForwardingList不可能對originalList中發生的情況有任何控制。 (無裝飾可以。)

你應該可能做的,總體來說,是什麼創造返回一個全新的裝修清單工廠方法,絕不可以讓你在所有訪問原始列表。

+0

+1這確實工作:) tnx的幫助! –

1

你試圖做的事很奇怪。原始列表對被約束一無所知,受限列表認爲他只是誰使用原始列表。所以只是不要使用原始列表來混淆它的裝飾版本。