2012-02-20 11 views
7

Me gustaría agregar una colección de objetos a un arrayList, solo si el atributo particular no es nulo.¿Debo extender ArrayList para agregar atributos que no sean nulos?

Estoy pensando en extender ArrayList e implementar el control dentro de la clase secundaria.

Una manera alternativa es verificar el atributo antes de ponerlo en un Arraylist, pero eso significa que tendré que dispersar el if si compruebo en todas partes si necesito agregar los objetos al arraylist basado en la lógica .

Me gustaría saber qué opinas sobre esto ... en un segundo pensamiento, ¿es una exageración?

Respuesta

20

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 LinkedListHibernate -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)); 
+6

+1 para composición sobre herencia! – helios

+0

+1 Gracias por la respuesta detallada – Sudhakar

1

Si desea hacer cumplir esto no veo por qué no (aunque debe comprobar el valor de retorno del método de agregar cada vez que lo agregue para asegurarse de que tuvo éxito).

Esta es una buena manera de deshacerse de esa lógica redundante que puede o no quedarse en iteraciones de software posteriores.

+0

Estoy de acuerdo con usted, pero la OMI tiene una desventaja cuando se extiende desde una implementación determinada de la lista: no es posible cambiar a una estrategia diferente, p. reemplace ArrayList con LinkedList. Delegación sería otra opción. – home

+0

@home Más o menos, es bastante fácil cambiar algo que extiende la lista de arrays a algo que se extiende a otra cosa, siempre y cuando las interfaces sean exactamente las mismas o algo cercanas. –

+0

Nuevamente, de acuerdo. +1 – home

0

El único problema sería si va a reutilizar este código y no recuerda que ha anulado la clase ArrayList, asegúrese de hacer un comentario exhaustivo.

1

No creo que sea una buena práctica. Considere en su lugar escribir un Util-Method en una Util-Class tomando dos parámetros: la lista de arreglos y el objeto que desea agregar. Allí puede verificar lo que quiera y puede reutilizar la lógica en todo su código.

Cuestiones relacionadas