2015-06-20 12 views
7

Sto creando un'applicazione contenente una classe che sto scrivendo chiamata Persona. Uno dei campi di Person è "alias" che è un ArrayList<String>. In definitiva gli alias verranno visualizzati all'utente secondo la seguente logica: Se la persona ha alias allora dovrebbero essere visualizzati come [Finch, Wren, Admin, etc...], altrimenti dovrebbe essere visualizzato UNKNOWN. Finora ho provato l'attuazione del presente in uno dei tre modi:Come gestire il valore predefinito di ArrayList

  1. persona contiene il metodo getAliases() che restituisce semplicemente una copia del ArrayList come è. Il chiamante controlla una matrice vuota per implementare il comportamento desiderato.

  2. La persona contiene il metodo aliasesToString() che può essere chiamato per produrre la stringa desiderata.

  3. Invece di utilizzare ArrayList<String>, l'alias è un'implementazione di DefaultableArrayList<T>. Questa classe estende ArrayList e contiene un valore predefinito con tipo T. Il metodo toString() viene sostituito per produrre la stringa desiderata. L'applicazione chiama some_person.getAliases().toString() per produrre il comportamento desiderato.

Qui di seguito è la mia realizzazione di opzione 3:

public class DefaultableArrayList<T> extends ArrayList<T> { 

    private static final long serialVersionUID = -6735356930885363889L; // Auto-generated 
    private final T defaultElement; 


    public DefaultableArrayList(T defaultElement) { 
     super(); 
     this.defaultElement = defaultElement; 
    } 


    public DefaultableArrayList(Collection<? extends T> c, T defaultElement) { 
     super(c); 
     this.defaultElement = defaultElement; 
    } 


    public DefaultableArrayList(int initialCapacity, T defaultElement) { 
     super(initialCapacity); 
     this.defaultElement = defaultElement; 
    } 


    public T getDefaultElement() { 
     return defaultElement; 
    } 


    @Override 
    public String toString() { 
     if (!isEmpty()) { 
      return super.toString(); 

     } else { 
      return defaultElement.toString(); 
     } 
    } 
} 

Quello che mi preoccupa sulle opzioni 2 e 3 è che potrei aggiungere complessità inutile mentre violare le linee guida OOP. La persona dovrebbe davvero preoccuparsi di ciò che accade se non ci sono alias e ha senso che gli alias definiscano come è implementato in definitiva nell'applicazione? Penso che dovrei lasciare che il chiamante gestisca il caso vuoto. Quale opzione dovrei scegliere per soddisfare al meglio le linee guida di progettazione OOP standard? O c'è una quarta opzione che non ho considerato?

risposta

6

La prima opzione è quella giusta. Il modello non dovrebbe preoccuparsi del modo in cui viene visualizzato.

Non rappresenterai la persona e il suo alias nello stesso modo in un'applicazione ricca, un'applicazione Web o un'applicazione console.

Anche in una determinata applicazione, probabilmente rappresenterai lo stesso modello in vari modi.

Se internazionalizzate la vostra applicazione, dovrete cambiare "SCONOSCIUTO" a qualcos'altro.

Quindi, è sufficiente restituire l'elenco come è (o una vew non modificabile della lista) e lasciare che il livello di presentazione gestisca la logica di presentazione. BTW, toString() è più un aiuto per il debug che un metodo funzionale utilizzato per rappresentare un oggetto in un'applicazione. passeggiata

2

Let attraverso le opzioni:

persona contiene le getAliases metodo(), che restituisce semplicemente il ArrayList come è. Il chiamante verifica la presenza di un array vuoto per implementare il comportamento desiderato .

Come sarebbe il codice del chiamante?

if (!person.getAliases().isEmpty()) { //Print aliases } 

Sembra un po 'brutto e illeggibile.Se si vuole andare con questa opzione, il minimo che puoi fare è aggiungere un metodo hasAliases in Person che fa in sostanza il controllo per voi e rende il codice del client più leggibile:

if (person.hasAliases()) { //Print aliases } 

Questo è molto più pulito e molto di più codice leggibile

La persona contiene il metodo aliasToString() che può essere chiamato per produrre la stringa desiderata.

L'idea di Person di essere autosufficiente non è negativa. Tutto ciò che il codice cliente deve fare è chiamare person.aliasesToString() piuttosto che fare:

if (person.hasAliases()) { 
    List<String> aliases = person.getAliases(); 
    StringBuilder aliaseString = new StringBuilder(""); 
    for (String alias : aliases) { 
     aliasString.append(aliases); 
    } 
} 

Invece di usare ArrayList, alias è un'implementazione di DefaultableArrayList

Questo è un eccessivo per un compito così semplice.

Quindi quale approccio segui? Dipende dal tuo requisito generale. Se hai clienti diversi/UI che vogliono fare cose diverse con gli alias, l'opzione 1 sarebbe la migliore. Se hai un singolo cliente che vuole sempre stampare gli alias in un certo modo, l'opzione 2 sarebbe una scelta migliore.

2

Trovo che il modo più semplice sia spesso di buon stile. Cioè, il codice più brutto quando si fa qualcosa di semplice di solito significa che lo stile sta andando fuori strada. Pertanto, l'Opzione 1 sembra un modo solido per implementare questo. Utilizzare getAliases() per restituire o stampare il campo è piuttosto standard. Inoltre, è possibile implementare un controllo per un array vuoto e restituire o stampare UNKNOWN in quell'istanza. Altrimenti, e ArrayList toString() si prenderà cura della formattazione del contenuto.

2

L'opzione 3 è un overkill. Non estenderei ArrayList per un così piccolo valore aggiunto.

La scelta tra l'opzione 1 e l'opzione 2 dipende dall'eventuale presenza di altri impieghi previsti per restituita da getAliases() oltre alla visualizzazione di una rappresentazione String di esso.

L'unico lato negativo che vedo con un metodo aliasesToString() è che presuppone che tutti gli utenti della classe Person visualizzino gli alias allo stesso modo.

Se si utilizza il metodo getAliases(), è preferibile che tale metodo restituisca una copia di tale Elenco o una rappresentazione di matrice di tale Elenco. Il motivo è che si impedisce all'utente della classe Person di mutare l'istanza Person mutando l'Elenco restituito da getAliases().

+2

Preferirei restituire una vista immutabile: 'Collections.unmodifiableList (aliases)'. –

+0

@JBNizet 'Collections.unmodifiableList (aliases)' è una buona alternativa. Protegge il membro dell'istanza originale da essere modificato e rende chiaro al chiamante del metodo che non possono mutare l'istanza Person mutando l'elenco degli alias. – Eran

+0

Sì, certo, scusate non volevo implicare che avrei restituito un riferimento diretto. Era una svista. – Helios

Problemi correlati