2015-12-25 6 views
8

Ho una libreria client in cui sto effettuando chiamate remote http al mio servizio di restituzione e quindi restituisco List<DataResponse> al cliente che chiama la nostra libreria con la risposta che ottengo dal mio REST servizio insieme a eventuali errori se ci sono alcuni avvolto intorno all'oggetto DataResponse.Come evitare di costruire costruttori lunghi

public class DataResponse { 

    private final String response; 
    private final boolean isLink; 
    private final TypeOfId idType; 
    private final long ctime; 
    private final long lmd; 
    private final String maskInfo; 

    // below are for error stuff 
    private final ErrorCode error; 
    private final StatusCode status; 

    // constructors and getters here 

} 

Qui è la mia classe ErrorCode enum:

public enum ErrorCode { 

    // enum values 

    private final int code; 
    private final String status; 
    private final String description; 

    // constructors and getters 

} 

e qui è la mia classe StatusCode enum:

public enum StatusCode { 
    SUCCESS, FAILURE; 
} 

Come si può vedere nella mia classe DataResponse ho sacco di campi in modo In base a ciò ho un costruttore molto lungo e ogni volta che faccio un oggetto DataResponse ho una linea grande con new DataResponse(.......). In futuro potrei avere più campi ma per ora ho solo questi campi.

C'è un modo migliore che posso utilizzare per creare un oggetto DataResponse e quindi restituire List<DataResponse> dalla mia libreria?

+5

È possibile utilizzare il modello di builder. – YoungHobbit

+0

http://stackoverflow.com/a/6395981/3885376 –

+0

Non dipendono ancora da un costruttore. Hai molti campi? Sembra un lavoro per la decomposizione. Dai un'occhiata a [questa risposta] (http://stackoverflow.com/questions/33784390/object-oriented-design-how-important-is-encapsulation-when-therere-lots-of-da/33785266#33785266). Se ti senti ancora di passare troppi dati al costruttore in seguito, puoi utilizzare un modello di builder. Anche se la corretta decomposizione di solito fa il trucco. Trovo che i builder siano utili per i parametri opzionali (per evitare costruttori telescopici che forniscono valori predefiniti, piuttosto che evitare molti parametri) –

risposta

14

Non utilizzare immediatamente lo builder pattern. Non è per i tipi con tonnellate di campi richiesti. È per i tipi con tonnellate di campi opzionali.

Le proprietà richieste dai costruttori sono specificate tramite il costruttore. Non sei obbligato a definire valori usando i metodi, il che rende questi valori facoltativi.

Questo lascia potenzialmente che il tuo oggetto venga costruito solo parzialmente. Usare un costruttore per questo sarebbe un abuso del design.


Detto questo, si dovrebbe decompose il tipo. Non sono sicuro di cosa sia lo lmd o ctime o che cosa dovrebbe rappresentare un DataResponse, quindi non posso dirti in che modo devi decomporsi. Ma posso dirti che cohesion è ciò che determina tale.

isLink, maskInfo e idType potrebbe essere scomposto in un oggetto DataResponseDetails:

class DataResponseDetails { 
    private boolean isLink; 
    private String maskInfo; 
    private TypeOfId idType; 

    public DataResponseDetails(boolean isLink, String maskInfo, TypeOfId idType) { 
     //... 
    } 
} 

Ora il vostro DataResponse potrebbe essere composto DataResponseDetails:

class DataResponse { 
    private DataResponseDetails details; 
    private String response; 
    //... 

    public DataResponse(DataResponseDetails details, String response, ...) { 
     //... 
    } 
} 

sentire il tuo costruttore richiede troppo ancora? Decompone di più!

+0

Vorrei aggiungere che, per me, dovrebbe essere considerata una buona pratica usare la classe opzionale (quella di Guava o Java 8) per i campi opzionali, per eliminare i valori nulli –

0

Come Joshua Bloch ha dichiarato nell'articolo 2 della seconda edizione di Java efficace, è consigliabile prendere in considerazione l'utilizzo di un modello di builder, poiché si tratta di una procedura consigliata.

Ecco cosa si codice potrebbe apparire come usarlo:

public class DataResponse { 

     private final String response; 
     private final boolean isLink; 
     private final TypeOfId idType; 
     private final long ctime; 
     private final long lmd; 
     private final String maskInfo; 

     // below are for error stuff 
     private final ErrorCode error; 
     private final StatusCode status; 

     // constructors and getters here 


     public static class Builder { 

      private final String response; 
      private final boolean isLink; 
      private final TypeOfId idType; 
      private final long ctime; 
      private final long lmd; 
      private final String maskInfo; 

      // below are for error stuff 
      private final ErrorCode error; 
      private final StatusCode status; 

      public Builder reponse(final String response) { 
       this.response = response; 
       return this; 
      } 

      public Builder isLing(final boolean isLink) { 
       this.isLink = isLink; 
       return this; 
      } 

      public DataResponse builder() { 
       return new DataResponse(this); 
      } 

      ... 

     } 

     private DataResponse(final Builder builder) { 
      this.response = builder.response; 
      this.isLink = builder.isLink; 
     } 
    } 

e poi fare qualcosa come segue:

DataResponse response = new DataResponse.Builder().reponse(anyResponse).isLink(isLink).build(); 
4

Forse è possibile identificare i gruppi logici più piccoli dei campi di spostarli in oggetti di una propria classe. Quindi puoi assemblare tutti questi oggetti negli oggetti DataResponse.