Обеспечение видимости памяти с помощью застройки/заводской шаблона

StackOverflow https://stackoverflow.com/questions/5376691

Вопрос

Следующий класс:

class Pizza {

    Ingredients ingredients;
    Price price;

    public setIngredients(Ingredients ing) {
        if (ingredients != null) {
            throw new IllegalStateException();
        }
        ingredients = ing;
        return this;
    }

    public setPrice(Price p) {
        if (price != null) {
            throw new IllegalStateException();
        }
        price = p;
        return this;
    }

}

можно использовать в схеме строителя, и после его построения, это эффективно неизменен, потому что каждое свойство может быть установлено только один раз. То есть:

Pizza pizza = new Pizza().setIngredients(something).setPrice(somethingelse);

Однако, Pizza не безопасно нить: нет никаких гарантий, что нить B видит ингредиенты, которые были вложены в него нитью A. Есть несколько способов исправить:

  • Сделать члены final. Анкет Но тогда вы не можете использовать шаблон строителя.
  • Синхронизировать доступ к участникам. Но это похоже на отходы, потому что они написаны только один раз.
  • Сделать их volatile. Анкет Ощущает отходы, как синхронизация.
  • Использовать AtomicReference.
  • Так далее.?

Мой вопрос: как лучше всего сказать JVM, что член класса не изменится после того, как какой -то метод был вызван? Должен ли я просто синхронизировать доступ к нему и поверить, что JVM оптимизирует замк? Это просто ощущается отходом, потому что я знать что член должен вести себя как это final после того, как он установлен. Разве нет лучших решений?

Это было полезно?

Решение

Образец застройщика обычно означает, что строитель является отдельным объектом. В этом случае вы можете сделать поля строительного объекта final, и инициализируйте их в конструкторе, называемом объектом Builder:

Pizza pizza = 
    new PizzaBuilder()
        .setIngredients(something)
        .setPrice(somethingelse)
        .build(); 

В качестве альтернативы вы можете обеспечить безопасную публикацию Pizza объект. Обратите внимание, что идиомы безопасной публикации применяются к поле, которое содержит ссылку на публикацию объекта, а не на поля самого объекта. Например, если pizza это поле какого -то объекта, вы можете сделать это volatile или синхронизировать доступ к нему - это обеспечит безопасную публикацию Pizza объект, назначенный этому поле.

Другие советы

Если значения участника никогда не предназначены для изменения, лучшая шаблон будет иметь Pizza конструктор, который принимает в качестве параметров Ingredients а также Price, и не имеют никаких методов сеттера на объекте вообще. На самом деле бесполезно иметь setSomething() Метод, который бросает исключение после того, как он называется.

Подумайте, как String классные работы. Как только вы создали создание String С некоторым текстом значение текста не может быть изменено. Единственный способ получить String с другим значением - это построить новый. Кажется, это то, что вы хотите здесь.

Использование этого шаблона также избегает проблемы синхронизации.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top