我遇到了一个非常讨厌的我会说'副作用',但这显然是一个糟糕的设计问题。我正在使用 Guava 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(),都委托给原始列表)
好的,您可能会看到,如果我使用原始的 add() 方法添加元素,我可能会超过最大尺寸...好吧,我想这是不可避免的(毕竟这在设计上并没有错)。但这对于 decoratedList 的设计并非如此。
我发现的唯一解决方法是:
List<String> decoratedList = factory.newTalendList(new ArrayList<String>(originalList), maximumSize);
但这似乎不是最好的方法(我不确定它是否适用于所有情况):我不是在装饰originalList,而是她的匿名克隆!我想知道:也许我完全搞砸了我的设计?有没有更好的方法来构建它?