2015-12-25 3 views
8

У меня есть клиентская библиотека, в которой я делаю http-удаленные вызовы для службы отдыха, а затем возвращаю List<DataResponse> обратно клиенту, который звонит в нашу библиотеку с ответом, который я получаю от своего REST службы вместе с любыми ошибками, если есть какие-либо обернутые вокруг объекта DataResponse.Как избежать создания длинных конструкторов

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 

} 

Вот мой ErrorCode перечисление класс:

public enum ErrorCode { 

    // enum values 

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

    // constructors and getters 

} 

А вот мой StatusCode перечисление класс:

public enum StatusCode { 
    SUCCESS, FAILURE; 
} 

Как вы можете увидеть в моем DataResponse классе у меня есть много полей, так Основа на том, что у меня очень длинный конструктор, и каждый раз, когда я делаю объект DataResponse, у меня есть большая строка с new DataResponse(.......). В будущем у меня может быть больше полей, но пока у меня есть только эти поля.

Есть ли какой-либо лучший способ, который я могу использовать для создания объекта DataResponse, а затем вернуть обратно List<DataResponse> из моей библиотеки?

+5

Вы можете использовать шаблон строителя. – YoungHobbit

+0

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

+0

Я бы не стал зависеть от строителя. У вас много полей? Звучит как работа для разложения. Проверьте [этот ответ] (http://stackoverflow.com/questions/33784390/object-oriented-design-how-important-is-encapsulation-when-therere-lots-of-da/33785266#33785266). Если вы все еще чувствуете, что впоследствии передаете слишком много данных конструктору, вы можете использовать шаблон построителя. Хотя правильное разложение обычно делает трюк. Я нахожу, что строители будут полезны для необязательных параметров (чтобы избежать конструкций телескопов, которые предоставляют значения по умолчанию, а не избегают множества параметров) –

ответ

14

Не используйте builder pattern сразу. Это не для типов с тоннами полей. Это для типов с тоннами опционально полей.

Требуемые свойства строителей задаются с помощью конструктора. Вы не обязаны определять значения с помощью методов, что делает эти значения необязательными.

Это оставляет потенциал для частичного строительства объекта. Использование построителя для этого было бы злоупотреблением дизайном.


С учетом этого вы должны decompose вашего типа. Я не уверен, что lmd или ctime, или действительно то, что должно представлять DataResponse, поэтому я не могу сказать вам, каким образом вы должны разлагаться. Но я могу сказать, что именно это определяет cohesion.

isLink, maskInfo и idType мог быть разложена на DataResponseDetails объекта:

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

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

Теперь ваш DataResponse может состоять из DataResponseDetails:

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

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

Живите конструктор требует еще слишком много? Разложите больше!

+0

Я бы добавил, что для меня лучше использовать дополнительный класс (один из Guava или Java 8) для необязательных полей, чтобы избавиться от нулевых значений –

0

Поскольку Джошуа Блох заявил об этом в пункте 2 Эффективного Java 2nd Edition, вам следует подумать об использовании шаблона построителя, так как это лучшая практика.

Вот что вы код может выглядеть следующим образом использовать его:

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

, а затем сделать что-то, как следующие:

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

Может быть, вы можете идентифицировать меньшие логические группы полей на перемещение их в объекты собственного класса. Затем вы можете собрать все эти объекты в своих объектах DataResponse.