Decorator
De hecho, me recomiendan envolver ArrayList
usando bien documentada Decorator patrón. Sólo tiene que envolver su ArrayList
con otro List
aplicación que delega la mayor parte de los métodos, pero añade lógica de validación:
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
}
Ventajas:
- todavía se puede acceder a la lista cruda sin validación si quieres (pero se puede restrinja esto)
- Es más fácil apilar diferentes validaciones, activarlas y desactivarlas selectivamente.
- Promueve composition over inheritance como señaló @helios
- Mejora la capacidad de prueba
- No atarte a un
List
aplicación específica, se puede añadir a la validación o LinkedList
Hibernate -backed listas persistentes. Incluso puede pensar en el decorador genérico Collection
para validar cualquier colección.
Implementación señala
A pesar de la aplicación recuerde que hay un buen montón de métodos que hay que recordar acerca mientras se sobreescriben: (?) add()
, addAll()
, set()
, subList()
, etc.
también su el objeto debe ser inmutable, de lo contrario el usuario puede agregar/establecer un objeto válido y modificarlo posteriormente para violar el contrato.
buen diseño orientado a objetos
Finaly me escribió:
validate(element)
pero tenga en cuenta:
element.validate()
que es un mejor diseño.
validaciones de apilamiento
Como se ha señalado antes, si desea apilar las validaciones, validando cada proprty/Apsect en una sola clase, por separado, considere el siguiente lenguaje:
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);
}
... y pocas implementaciones :
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
}
}
¿Quieres sólo para validar foo?
List<MyBusinessObject> list = new FooValidatingDecorator(rawArrayList);
desea validar tanto foo y bar ?
List<MyBusinessObject> list =
new BarValidatingDecorator(new FooValidatingDecorator(rawArrayList));
+1 para composición sobre herencia! – helios
+1 Gracias por la respuesta detallada – Sudhakar