我应该扩展ArrayList以添加非null的属性吗?
我想将一个对象集合添加到arrayList,只有当特定属性不为null时。
我正在考虑扩展ArrayList并在子类中实现检查。
另一种方法是在将它放入Arraylist之前检查属性,但这意味着,如果我需要根据逻辑将对象添加到arraylist,我必须分散if检查每个位置。
我想知道你对它的想法……再想一想,这是一种矫枉过正吗?
装饰图案
我实际上建议使用记录良好的Decorator模式包装ArrayList
。 您只需将ArrayList
与另一个List
实现包装在一起,该实现委派大多数方法,但添加了validation逻辑:
public class ValidatingListDecorator extends AbstractList { private final List target; public ValidatingListDecorator(List target) { this.target = target; } @Override public MyBusinessObject set(int index, MyBusinessObject element) { validate(element); return target.set(index, element); } @Override public boolean add(MyBusinessObject o) { validate(o); return target.add(o); } //few more to implement }
优点:
- 如果需要,您仍然可以访问原始列表而无需validation(但您可以限制此操作)
- 更容易堆叠不同的validation,有选择地打开和关闭它们。
- 如@helios所述,促进组合而不是inheritance
- 提高可测试性
- 不会将您绑定到特定的
List
实现,您可以向LinkedList
或Hibernate -backed持久列表添加validation。 您甚至可以考虑使用通用Collection
装饰器来validation任何集合。
实施说明
尽管实现了,但是在重写时需要记住很多方法: add()
, addAll()
, set()
, subList()
(?)等。
此外,您的对象必须是不可变的,否则用户可以添加/设置有效对象,然后修改它以违反合同。
良好的OO设计
最后我写道:
validate(element)
但考虑一下:
element.validate()
这是一个更好的设计。
堆叠validation
如前所述,如果要堆叠validation,在单个单独的类中validation每个proprty / apsect,请考虑以下习惯用法:
public abstract class ValidatingListDecorator extends AbstractList { private final List target; public ValidatingListDecorator(List target) { this.target = target; } @Override public MyBusinessObject set(int index, MyBusinessObject element) { validate(element); return target.set(index, element); } protected abstract void validate(MyBusinessObject element); }
……并且很少实现:
class FooValidatingDecorator extends ValidatingListDecorator { public FooValidatingDecorator(List target) { super(target); } @Override protected void validate(MyBusinessObject element) { //throw if "foo" not met } } class BarValidatingDecorator extends ValidatingListDecorator { public BarValidatingDecorator(List target) { super(target); } @Override protected void validate(MyBusinessObject element) { //throw if "bar" not met } }
想只validationfoo ?
List list = new FooValidatingDecorator(rawArrayList);
想validationfoo和bar ?
List list = new BarValidatingDecorator(new FooValidatingDecorator(rawArrayList));
如果你想强制执行此操作,我不明白为什么不这样做(尽管你应该在添加时检查add方法的返回值,以确保它成功)。
这是摆脱冗余逻辑的好方法,这种冗余逻辑在以后的软件迭代中可能会或可能不会存在。
我认为这不是一个好习惯。 考虑使用两个参数在Util-Class中编写Util-Method:数组列表和您想要添加的对象。 在那里,您可以检查您想要的任何内容,并可以在您的代码中重用逻辑。
唯一的问题是如果你去重用这个代码并且你不记得你已经覆盖了ArrayList类,请确保彻底评论。