Java 如何避免长构造函数

Java 如何避免长构造函数,java,constructor,enums,Java,Constructor,Enums,我有一个客户端库,在该库中,我对我的rest服务进行http远程调用,然后我将列表返回给调用我们库的客户,该客户使用我从我的rest服务获得的响应以及任何错误(如果有任何环绕数据响应对象) public class DataResponse { private final String response; private final boolean isLink; private final TypeOfId idType; private final long

我有一个客户端库,在该库中,我对我的rest服务进行http远程调用,然后我将
列表
返回给调用我们库的客户,该客户使用我从我的rest服务获得的响应以及任何错误(如果有任何环绕
数据响应
对象)

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
enum类:

public enum ErrorCode {

    // enum values

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

    // constructors and getters

}
public enum StatusCode {
    SUCCESS, FAILURE;
}
这是我的
StatusCode
enum类:

public enum ErrorCode {

    // enum values

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

    // constructors and getters

}
public enum StatusCode {
    SUCCESS, FAILURE;
}
正如您在我的
DataResponse
类中所看到的,我有很多字段,因此我有一个很长的构造函数,每次我创建
DataResponse
对象时,我都会对
新的DataResponse(……)
进行大量排序。将来我可能会有更多的字段,但现在我只有这些字段


有没有比java更好的方法来制作<代码>数据响应> /代码>对象,然后从我的库中返回代码<清单>代码>?< /p> < p>正如Joshua Bloch在有效Java第二版的第2条中所陈述的,你应该考虑使用构造器模式,因为这是一个最佳实践。 下面是您使用它编写代码的样子:

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

也许您可以识别较小的逻辑字段组,并将它们移动到自己类的对象中。然后可以将所有这些对象组合到
DataResponse
对象中

不要立即使用。它不适用于具有大量必填字段的类型。它适用于具有大量可选字段的类型

构建器所需的属性通过构造函数指定。您不会被迫使用方法定义值,这使得这些值是可选的

这使得您的对象可能只被部分构造。使用构建器进行此操作将是对设计的滥用


话虽如此,你还是应该选择你喜欢的类型。我不确定什么是
lmd
ctime
,也不确定
DataResponse
应该代表什么,所以我无法告诉您应该以何种方式分解。但我可以告诉你,是什么决定了这一切

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, ...) {
        //...
    }
}

你觉得你的构造器需要太多的静物吗?分解更多

您可以使用生成器模式。我还不需要依赖生成器。你有很多领域?听起来像是分解的工作。退房如果您仍然觉得之后向构造函数传递了太多数据,那么可以使用构建器模式。虽然适当的分解通常会起作用。我发现构造器对于可选参数很有用(避免压缩提供默认值的构造器,而不是避免大量参数)@AshishAni我认为你没有正确解释这一章。我也读过有效的Java,它使用营养信息作为构建器的示例-一些营养值是可选的,因此构建器模式是一个很好的设计scenario@YoungHobbit读我的答案。它详细说明了为什么构建器模式不适合“大量的构造函数参数”。我很惊讶这么多人误解了这个模式的目的。我想补充一点,对我来说,使用可选类(来自Guava或Java8的类)作为可选字段,以消除空值,应该被认为是一种最佳实践