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 ?
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 toLinkedList
or Hibernate-backed persistent lists. You can even think about genericCollection
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));
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.
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.
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.
来源:https://stackoverflow.com/questions/9358821/should-i-extend-arraylist-to-add-attributes-that-isnt-null