Should I extend ArrayList to add attributes that isn't null?

前端 未结 4 798
孤街浪徒
孤街浪徒 2020-12-30 09:45

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

相关标签:
4条回答
  • 2020-12-30 10:31

    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));
    
    0 讨论(0)
  • 2020-12-30 10:36

    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.

    0 讨论(0)
  • 2020-12-30 10:36

    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.

    0 讨论(0)
  • 2020-12-30 10:41

    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.

    0 讨论(0)
提交回复
热议问题