我遇到一个非常讨厌的问题,我会说“副作用”,但这显然是不良设计的问题。我正在使用番石榴ForwardingList模式来装饰常规列表。我的目的是建立一个大小限制列表,其中当满足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(),都委托给原始List)

好的,您可能会看到,如果我使用原始的add()方法添加一个元素,我可以超过maximumsize ...好的,我想这是不可避免的(毕竟这在设计上没有错)。但这不是针对装饰列表设计的。

我发现的唯一解决方法是:

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


但这似乎不是最好的方法(而且我不确定它是否在每种情况下都有效):我不是装饰originalList,而是装饰她的匿名克隆!我想知道:也许我完全搞砸了我的设计?有没有更好的方法来构建它?

最佳答案

这种模式起作用的唯一方法是,在创建装饰器后再也不要引用originalListForwardingList可能无法控制originalList中发生的事情。 (没有装饰员可以。)

总的来说,您可能应该做的是创建一个工厂方法,该方法返回一个全新的修饰列表,并且从不让您访问原始列表。

10-05 21:14