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

发布于 2025-01-07 09:49:06 字数 205 浏览 6 评论 0原文

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

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

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

我想知道你对此的想法……再想一想,这是不是太过分了?

I would like to add a collection of objects to an arrayList ,only if the particular attribute is not null.

I am thinking of extending the ArrayList and implementing the check inside the child class.

One alternate way is to check for the the attribute before putting it in a Arraylist, but that would mean , i will have to scatter the if checks every where if i need to add the objects to the arraylist based on the logic.

I would like to know your thoughts on it ... on a second thought is it a overkill ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦在夏天 2025-01-14 09:49:06

装饰器模式

我实际上建议使用记录良好的装饰器来包装ArrayList em> 模式。您只需用另一个 List 实现包装您的 ArrayList,该实现委托大多数方法,但添加验证逻辑:

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所述
  • 提高可测试性
  • 不捆绑如果您要使用特定的 List 实现,您可以向 LinkedListHibernate 支持的持久列表。您甚至可以考虑使用通用 Collection 装饰器来验证任何集合。

实现注意事项

尽管实现了,但请记住,在重写时您必须记住很多方法:add()addAll()set()< /code>、subList() (?) 等。

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

良好的 OO 设计

最后我写道:

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));

Decorator pattern

I would actually recommend wrapping ArrayList using well-documented Decorator pattern. You simply wrap your ArrayList with another List implementation that delegates most of the methods but adds validation logic:

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
    
}

Advantages:

  • You can still access raw list without validation if you want (but you can restrict this)
  • Easier to stack different validations, turn them on and off selectively.
  • Promotes composition over inheritance as noted by @helios
  • Improves testability
  • Does not tie you to a specific List implementation, you can add validation to LinkedList or Hibernate-backed persistent lists. You can even think about generic Collection decorator to validate any collection.

Implementation notes

Despite the implementation remember there are quite a lot of methods you have to remember about while overriding: add(), addAll(), set(), subList() (?), etc.

Also your object must be immutable, otherwise the user can add/set valid object and modify it afterwards to violate the contract.

Good OO design

Finaly I wrote:

validate(element)

but consider:

element.validate()

which is a better design.

Stacking validations

As noted before if you want to stack validations, validating each proprty/apsect in a single, separate class, consider the following idiom:

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);

}

...and few implementations:

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
    }
}

Want to only validate foo?

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

Want to validate both foo and bar?

List<MyBusinessObject> list = 
  new BarValidatingDecorator(new FooValidatingDecorator(rawArrayList));
夏日落 2025-01-14 09:49:06

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

这是消除冗余逻辑的好方法,这些逻辑在以后的软件迭代中可能会存在,也可能不会存在。

If you would like to enforce this I don't see why not (although you should check the return value of the add method whenever you do add to make sure that it succeeded).

This is a good way to get rid of that redundant logic which may or may not stick around in later software iterations.

云归处 2025-01-14 09:49:06

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

I don't think this is a good practice. Consider instead writing a Util-Method in a Util-Class taking two parameters: The array list and the object you would like to add. There you can check whatever you want and can reuse the logic all over your code.

旧瑾黎汐 2025-01-14 09:49:06

唯一的问题是,如果您要重用此代码并且您不记得您已经重写了 ArrayList 类,请确保彻底注释。

Only issue would be if you go to reuse this code and you don't remember you've overriden the ArrayList class, make sure to comment thoroughly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文