我应该扩展ArrayList以添加非null的属性吗?

时间:2012-02-20 09:30:55

标签: java arraylist abstraction reusability

我想将一个对象集合添加到arrayList,只有当特定属性不为null时才会这样。

我正在考虑扩展ArrayList并在子类中实现检查。

另一种方法是在将它放入Arraylist之前检查属性,但这意味着,如果我需要根据逻辑将对象添加到arraylist,我必须分散if检查每个位置。

我想知道你对它的想法......再想一想,这是一种过度杀伤吗?

4 个答案:

答案 0 :(得分:22)

装饰者模式

我实际上建议使用记录良好的Decorator模式包装ArrayList。您只需将ArrayList与另一个List实现包装在一起,该实现委派大多数方法,但添加了验证逻辑:

public class ValidatingListDecorator extends AbstractList<MyBusinessObject>
{

    private final List<MyBusinessObject> target;

    public ValidatingListDecorator(List<MyBusinessObject> 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

}

优点:

  • 如果您愿意,您仍然可以访问原始列表而无需验证(
  • 更容易堆叠不同的验证,有选择地打开和关闭它们。
  • @helios
  • 所述,宣传composition over inheritance
  • 提高可测试性
  • 不会将您绑定到特定的List实现,您可以向LinkedListHibernate支持的持久列表添加验证。您甚至可以考虑使用通用Collection装饰器来验证任何集合。

实施说明

尽管实现了记住,但在重写时需要记住很多方法:add()addAll()set()subList()(?)等

此外,您的对象必须是不可变的,否则用户可以添加/设置有效对象,然后修改它以违反合同。

良好的OO设计

最后我写道:

validate(element)

但请考虑:

element.validate()

这是一个更好的设计。

堆叠验证

如前所述,如果你想要堆叠验证,验证一个单独的类中的每个proprty / apsect,请考虑以下习语:

public abstract class ValidatingListDecorator extends AbstractList<MyBusinessObject>
{

    private final List<MyBusinessObject> target;

    public ValidatingListDecorator(List<MyBusinessObject> 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<MyBusinessObject> target)
    {
        super(target);
    }

    @Override
    protected void validate(MyBusinessObject element)
    {
        //throw if "foo" not met
    }
}

class BarValidatingDecorator extends ValidatingListDecorator {

    public BarValidatingDecorator(List<MyBusinessObject> target)
    {
        super(target);
    }

    @Override
    protected void validate(MyBusinessObject element)
    {
        //throw if "bar" not met
    }
}

只想验证 foo

List<MyBusinessObject> list = new FooValidatingDecorator(rawArrayList);

想验证 foo bar 吗?

List<MyBusinessObject> list = 
  new BarValidatingDecorator(new FooValidatingDecorator(rawArrayList));

答案 1 :(得分:1)

如果您想强制执行此操作,我不明白为什么不这样做(尽管您应该在添加时检查add方法的返回值,以确保它成功)。

这是摆脱冗余逻辑的好方法,这种逻辑可能会或可能不会在以后的软件迭代中出现。

答案 2 :(得分:1)

我认为这不是一个好习惯。考虑使用两个参数在Util-Class中编写Util-Method:数组列表和您想要添加的对象。在那里,您可以检查您想要的任何内容,并可以在您的代码中重复使用逻辑。

答案 3 :(得分:0)

唯一的问题是如果你去重用这段代码并且你不记得你已经覆盖了ArrayList类,请务必彻底评论。