Как использовать значение по умолчанию в шаблоне компоновщика, если это значение не передается, а также сделать потокобезопасным?


Я пытаюсь использовать шаблон Builder для своего класса..

Ниже приведен мой класс Builder, который я построил, следуя версии Джошуа Блоха, как он показал в Effective Java, 2nd Edition. Наш клиент в основном пройдет userId, clientId всегда, но другие поля являются необязательными, и они могут передавать или не передавать его. Здесь предпочтение-это класс 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 можно использовать несколько раз, чтобы построить ключи, это не один раз. Независимо от идентификатора пользователя и идентификатора ClientID они будут получать, они будут снова строить InputKeys.

2 2

2 ответа:

Просто инициализируйте тайм-аут до 500 в Builder. Метод timeout перезапишет это значение, если его вызвать.

protected long timeout = 500L;

Вы можете инициализировать значение таймаута в конструкторе Builder (или при объявлении переменной), например

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

Таким образом, если вы не вызываете метод timeout(), он будет иметь значение по умолчанию, в противном случае он будет установлен на значение, переданное через timeout().

Что касается потокобезопасности, если конструктор Builder используется только для создания нового объекта InputKeys (как в сценарии, описанном в вопросе), без какой-либо другой области кода, имеющей доступ к этому объекту InputKeys, не существует нужно применить какую-то дополнительную защиту.