다음 클래스 :보장 메모리 가시성
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
이 설정된 후처럼 동작해야하므로 낭비라고 느껴집니다. 더 나은 해결책이 없습니까?
예외가 처음 호출 된 후 예외를 throw하는'setSomething()'메소드의 아이디어는 해당 멤버의 효과적인 불변 속성을 적용하는 것이다.물론 모든 것이 '최종'일 수 있으며, 20 개의 인수를 사용하는 생성자가 있습니다.하지만이를 피하는 것이 AFAIK 빌더 패턴의 한 포인트입니다. –
하지만이 경우에는 20 개가 아니라 2 개의 인수 만 있습니다. 걱정이된다면 axtavt의 대답을 제안하십시오. _always_ 작동하는 setter를 가진'PizzaBuilder' 클래스를 가질 수 있으며'build()'(또는 개인적으로'toPizza()'를 사용할 때까지'Pizza' 인스턴스가 생성되지 않습니다. 그래서'Pizza' 생성자에 대해 알아야 할 유일한 곳은'PizzaBuilder'입니다. 다른 모든 사람들은''Pizza'를 얻기 위해서는''PizzaBuilder''를 사용해야합니다. – aroth