Обеспечение видимости памяти с помощью застройки/заводской шаблона
-
28-10-2019 - |
Вопрос
Следующий класс:
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
с другим значением - это построить новый. Кажется, это то, что вы хотите здесь.
Использование этого шаблона также избегает проблемы синхронизации.