2012-02-20 25 views
7

Vorrei aggiungere una raccolta di oggetti a una lista di array, solo se l'attributo particolare non è nullo.Devo estendere ArrayList per aggiungere attributi non nulli?

Sto pensando di estendere ArrayList e implementare il controllo all'interno della classe figlio.

Un modo alternativo è quello di verificare l'attributo prima di inserirlo in un Arraylist, ma ciò significherebbe, dovrò spargere i controlli if ogni dove se ho bisogno di aggiungere gli oggetti all'arrayist in base alla logica .

Mi piacerebbe sapere cosa ne pensate ... un secondo pensiero è eccessivo?

risposta

20

modello Decorator

vorrei davvero raccomandare avvolgendo ArrayList utilizzando ben documentata Decorator modello. È sufficiente avvolgere il vostro ArrayList con un'altra List implementazione che i delegati maggior parte dei metodi, ma aggiunge la logica di convalida:

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 

} 

Vantaggi:

  • è ancora possibile accedere elenco grezzo senza convalida se si vuole (ma si può limitare questo)
  • Più facile impilare diverse convalide, attivarle e disattivarle in modo selettivo.
  • Promuove composition over inheritance come notato da @helios
  • Migliora testability
  • non ti legare ad una specifica List implementazione, è possibile aggiungere la convalida di LinkedList o Hibernate emessi a fronte di liste persistenti. Puoi anche pensare al decoratore Collection generico per convalidare qualsiasi collezione.

Note applicative

Nonostante l'attuazione Ricorda che ci sono un sacco di metodi che dovete ricordare circa mentre l'override: (?) add(), addAll(), set(), subList(), ecc

anche il tuo l'oggetto deve essere immutabile, altrimenti l'utente può aggiungere/impostare un oggetto valido e modificarlo in seguito per violare il contratto.

buona progettazione OO

Finaly ho scritto:

validate(element) 

ma prendere in considerazione:

element.validate() 

che è un design migliore.

impilabili convalide

Come notato prima, se si desidera impilare le convalide, convalidando ogni proprty/Apsect in un unico, classe separata, si consideri il seguente linguaggio:

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

} 

... e poche implementazioni :

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

desidera convalidare solo foo?

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

desidera convalidare sia foo e bar?

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

+1 per la composizione sull'ereditarietà! – helios

+0

+1 Grazie per la risposta molto dettagliata – Sudhakar

1

Se si desidera applicare questo non vedo perché no (anche se è necessario verificare il valore restituito del metodo add ogni volta che si aggiunge per assicurarsi che sia riuscito).

Questo è un buon modo per sbarazzarsi di quella logica ridondante che può o meno rimanere nelle iterazioni software successive.

+0

Sono d'accordo con te, ma IMO c'è un compromesso quando si estende da una certa implementazione di lista - non è possibile passare a una strategia diversa, ad es. sostituire ArrayList con LinkedList. La delega sarebbe un'altra opzione. – home

+0

@home In alcuni casi, è abbastanza semplice cambiare qualcosa che estenda l'array al proprio interno, estendendo qualcos'altro purché le interfacce siano esattamente uguali o piuttosto vicine. –

+0

Ancora, d'accordo. +1 – home

0

Unico problema sarebbe se si riutilizzi questo codice e non ricordi di aver superato la classe ArrayList, assicurati di commentare a fondo.

1

Non penso che sia una buona pratica. Considera invece di scrivere un Metodo Util in una Util-Class prendendo due parametri: l'elenco di array e l'oggetto che desideri aggiungere. Qui puoi controllare ciò che vuoi e riutilizzare la logica in tutto il tuo codice.

Problemi correlati