如何使用包含所有参数的构建器模式作为必需参数?

时间:2015-12-26 05:07:58

标签: java design-patterns builder builder-pattern

我有一个构建器模式,其中很可能我的所有参数都是必需的,所以我创建了一个长构造函数,如下面的代码所示。

public final class ResponseHolder {

    // all below six are related to response information
    private final String response;
    private final boolean isLinking;
    private final TypeHold typeOfId;
    private final long userTimeInMs;
    private final long userLmdInDays;
    private final String maskInfo;

    // below two are related to error handling
    private final ErrorCode error;
    private final StatusCode status;

    private ResponseHolder(Builder builder) {
        this.response = builder.response;
        this.isLinking = builder.isLinking;
        this.typeOfId = builder.typeOfId;
        this.userTimeInMs = builder.userTimeInMs;
        this.userLmdInDays = builder.userLmdInDays;
        this.maskInfo = builder.maskInfo;
        this.error = builder.error;
        this.status = builder.status;
    }

    public static class Builder {
        protected final String response;
        protected final TypeHold typeOfId;
        protected final String maskInfo;
        protected final ErrorCode error;
        protected final StatusCode status;
        protected final boolean isLinking;
        protected final long userTimeInMs;
        protected final long userLmdInDays;


        public Builder(String response, TypeHold typeOfId, String maskInfo, ErrorCode error,
                StatusCode status, boolean isLinking, long userTimeInMs, long userLmdInDays) {
            this.response = response;
            this.typeOfId = typeOfId;
            this.maskInfo = maskInfo;
            this.error = error;
            this.status = status;
            this.isLinking = isLinking;
            this.userTimeInMs = userTimeInMs;
            this.userLmdInDays = userLmdInDays
        }

        public ResponseHolder build() {
            return new ResponseHolder(this);
        }
    }

    // getters here
}

现在,当所有参数都是强制性的时候,我会感到困惑,那么它是如何有用的呢?有没有更好的方式来表示我上面的Builder模式?可以在逻辑上将传入的参数分组到它们自己的类中,以减少传递给构建器构造函数的参数数量?

虽然拥有单独的对象可以简化一些事情,但如果不熟悉代码,也会使事情变得有点难以理解。我可以做的一件事是将所有参数移动到他们自己的addParam(param)方法中,然后在运行时对build()方法中的必需参数进行验证?

我应该遵循的最佳做法是什么,我可以在这里使用更好的方法吗?

2 个答案:

答案 0 :(得分:4)

许多 不同的有效参数排列允许您创建对象时,Builder模式会发光。如果没有Builder模式,您将被迫创建许多丑陋且令人困惑的构造函数来处理所有可能的有效参数组合。

但在您的情况下,只有 一个 有效的参数集可以让您创建对象。这正是构造函数的用途。在这里使用Builder模式不仅有点过分,而且根本不合适。

只需为ResponseHolder类使用普通构造函数。

答案 1 :(得分:4)

构建器模式的目的是在构造目标对象之前,使用无参数构造函数,许多命名良好的setter方法和最终完成方法,该方法验证给定值的组合是否有效。

在您的情况下,由于所有值都是必需的,因此构建器模式的主要目的是提供一种命名参数支持。

此外,您的目标对象应该有多个arg构造函数,而不是将构建器对象作为参数)

因此,您的构建器应该是(假设不允许空值):

public static class Builder {
    private String     response;
    private TypeHold   typeOfId;
    private String     maskInfo;
    private ErrorCode  error;
    private StatusCode status;
    private Boolean    isLinking;
    private Long       userTimeInMs;
    private Long       userLmdInDays;

    public Builder setResponse(String response) {
        this.response = response;
        return this;
    }
    public Builder setTypeOfId(TypeHold typeOfId) {
        this.typeOfId = typeOfId;
        return this;
    }
    public Builder setMaskInfo(String maskInfo) {
        this.maskInfo = maskInfo;
        return this;
    }
    public Builder setError(ErrorCode error) {
        this.error = error;
        return this;
    }
    public Builder setStatus(StatusCode status) {
        this.status = status;
        return this;
    }
    public Builder setIsLinking(boolean isLinking) {
        this.isLinking = isLinking;
        return this;
    }
    public Builder setUserTimeInMs(long userTimeInMs) {
        this.userTimeInMs = userTimeInMs;
        return this;
    }
    public Builder setUserLmdInDays(long userLmdInDays) {
        this.userLmdInDays = userLmdInDays;
        return this;
    }
    public ResponseHolder build() {
        if (this.response == null ||
            this.typeOfId == null ||
            this.maskInfo == null ||
            this.error == null ||
            this.status == null ||
            this.isLinking == null ||
            this.userTimeInMs == null ||
            this.userLmdInDays == null) {
            throw new IllegalStateException("Not all required values given");
        }
        return new ResponseHolder(this.response,
                                  this.typeOfId,
                                  this.maskInfo,
                                  this.error,
                                  this.status,
                                  this.isLinking,
                                  this.userTimeInMs,
                                  this.userLmdInDays);
    }
}

您现在可以像这样使用它:

ResponseHolder holder = new ResponseHolder.Builder()
                        .setResponse(response)
                        .setTypeOfId(typeOfId)
                        .setMaskInfo(maskInfo)
                        .setError(error)
                        .setStatus(status)
                        .setIsLinking(isLinking)
                        .setUserTimeInMs(userTimeInMs)
                        .setUserLmdInDays(userLmdInDays)
                        .build();