如何避免制作长构造函数
我有一个客户端库,我正在对我的rest服务进行http远程调用,然后我将List
返回给正在调用我们的库的客户,我从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
?
不要立即使用构建器模式 。 它不适用于具有大量必填字段的类型。 它适用于包含大量可选字段的类型。
通过构造函数指定构建器的必需属性。 您不必使用方法定义值,这使得这些值是可选的。
这样,您的对象只能部分构建 。 使用构建器可能会滥用设计。
话虽如此,你应该分解你的类型。 我不确定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, ...) { //... } }
感觉你的构造函数需要太多了吗? 分解更多!
也许你可以识别较小的逻辑字段组,将它们移动到自己类的对象中。 然后,您可以在DataResponse
对象中组合所有这些对象。
正如Joshua Bloch在Effective Java 2nd Edition的第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();