7

我正在尝试为我的班级使用 Builder Pattern..

下面是我按照 Joshua Bloch 在 Effective Java, 2nd Edition 中展示的版本构建的 Builder 类。我们的客户通常会通过userIdclientId但其他字段是可选的,他们可能会通过也可能不会通过。这里的 Preference 是一个包含四个字段的 ENUM 类。

public final class InputKeys {

    private long userid;
    private long clientid;
    private long timeout = 500L;
    private Preference pref;
    private boolean debug;
    private Map<String, String> parameterMap;

    private InputKeys(Builder builder) {
        this.userid = builder.userId;
        this.clientid = builder.clientId;
        this.pref = builder.preference;
        this.parameterMap = builder.parameterMap;
        this.timeout = builder.timeout;
        this.debug = builder.debug;
    }

    public static class Builder {
        protected final long userId;
        protected final long clientId;
        protected long timeout;
        protected Preference preference;
        protected boolean debug;
        protected Map<String, String> parameterMap;

        public Builder(long userId, long clientId) {
            this.userId = userId;
            this.clientId = clientId;
        }

        public Builder parameterMap(Map<String, String> parameterMap) {
            this.parameterMap = parameterMap;
            return this;
        }

        public Builder preference(Preference preference) {
            this.preference = preference;
            return this;
        }

        public Builder debug(boolean debug) {
            this.debug = debug;
            return this;
        }

        public Builder timeout(long timeout) {
            this.timeout = timeout;
            return this;
        }

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

下面是我的枚举类 -

public enum Preference {
    PRIMARY,
    SECONDARY
}    

我正在拨打这样的电话来构造InputKeys参数 -

InputKeys keys = new InputKeys.Builder(12000L, 33L).build();    
System.out.println(keys);

我在这里看到的唯一问题是,如果客户没有传递任何超时值,我需要始终将默认超时值设置为 500,但如果他们传递任何超时值,那么它应该覆盖我的默认超时值。这对我不起作用,因为当我keys在调试模式下看到我的时,它的超时值始终为 0。

有什么我想念的吗?而且我也试图使这个类不可变和线程安全。这是一个线程安全和不可变版本的 Builder 还是我错过了什么?

更新:-

人们将使用它的特定场景是我们有一个工厂,客户将使用它来调用我们的代码。我们有一个简单的接口,我们的一个类正在实现它,然后我们有一个工厂,我们将通过该工厂调用该实现的某个方法,该方法接受该keys参数。

所以他们将在应用程序中使用下面的代码进行调用,并且他们可能会在多线程环境中运行应用程序。

InputKeys keys = new InputKeys.Builder(12000L, 33L).build();    

IClient client = ClientFactory.getInstance();
client.getData(keys);

然后 InputKeys Builder 可以多次使用来构造键,不是一次。无论他们将获得什么 userId 和 clientId,他们都将再次构造 InputKeys。

4

2 回答 2

4

只需在Builder. timeout如果调用该方法,它将覆盖此值。

protected long timeout = 500L;
于 2014-01-10T20:46:17.923 回答
3

Builder您可以在构造函数中(或在变量声明中)初始化超时值,例如

public Builder(long userId, long clientId) {
    this.userId = userId;
    this.clientId = clientId;
    this.timeout = 500L;
}

这样,如果不调用该timeout()方法,它将具有默认值,否则将设置为通过timeout().

关于线程安全,如果Builder构造函数仅用于创建新InputKeys对象(如问题中描述的场景),没有任何其他代码区域可以访问该InputKeys对象,则无需应用任何额外保护。

于 2014-01-10T20:59:06.780 回答