java - 我应该扩展 ArrayList 以添加不为空的属性吗?

标签 java arraylist abstraction reusability

我想将对象集合添加到 arrayList 中,前提是特定属性不为 null。

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

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

我想知道您对此有何看法……仔细想想,这是否有点矫枉过正?

最佳答案

装饰器模式

我实际上建议使用有据可查的 Decorator 包装 ArrayList图案。您只需将 ArrayList 包装在另一个 List 实现中,该实现委托(delegate)了大部分方法但添加了验证逻辑:

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
    
}

优点:

  • 如果你愿意,你仍然可以在没有验证的情况下访问原始列表(但你可以限制这一点)
  • 更容易堆叠不同的验证,有选择地打开和关闭它们。
  • 推广 composition over inheritance正如@helios
  • 所说
  • 提高可测试性
  • 不会将您绑定(bind)到特定的 List 实现,您可以将验证添加到 LinkedListHibernate支持的持久列表。您甚至可以考虑使用通用 Collection 装饰器来验证任何集合。

实现说明

尽管要记住实现,但在覆盖时必须记住很多方法:add()addAll()set() , subList() (?), 等等

此外,您的对象必须是不可变的,否则用户可以添加/设置有效对象并在事后修改它以违反契约(Contract)。

良好的面向对象设计

最后我写道:

validate(element)

但请考虑:

element.validate()

哪个设计更好。

堆叠验证

如前所述,如果您想堆叠验证,在一个单独的类中验证每个属性/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);

想要同时验证 foobar 吗?

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

关于java - 我应该扩展 ArrayList 以添加不为空的属性吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9358821/

相关文章:

java - For循环只执行一次迭代

java - 查找集合内的值并比较值字段

java - 搜索 ArrayList 对象

php - Mysqli 抽象,从准备好的语句中获取数组

mysql - Yii2/PHP : Abstracting Database Access for InfluxDB and MySQL

java - Word XML 到 RTF 转换

java - 在java动态web项目中找不到图像

java - 递归方法,接受输入 s 和 k 并生成长度为 k 的所有字符串

java - ArrayList 类型不是泛型;它不能用参数参数化

c# - 使用枚举来选择要实例化的类