/** * 코드 2-4 계층적으로 설계된 클래스와 잘 어울리는 빌더 패턴 (19쪽) * * 참고: 여기서 사용한 '시뮬레이트한 셀프 타입(simulated self-type)' 관용구는 * 빌더뿐 아니라 임의의 유동적인 계층구조를 허용한다. */ public abstract class Pizza { public enum Topping {HAM, MUSHROOM, ONION, PEPPER, SAUSAGE} final Set<Topping> toppings; /** * 추상 빌더 - 재귀적인 타입 제안 */ abstract static class Builder<T extends Builder<T>> { EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class); public T addTopping(Topping topping) { toppings.add(Objects.requireNonNull(topping)); /** * this 를 반환할 경우 Builder<T>를 반환하게 되고 이는 하위 타입이 아닌 자기 자신 즉 Pizza 를 return * self()를 반환해야 하위 클래스를 반환 (Calzone 혹은 NyPizza) */ return self(); } abstract Pizza build(); /** * 하위 클래스는 이 메서드를 재정의(overriding)하여 * "this"를 반환하도록 해야 한다. */ protected abstract T self(); } Pizza(Builder<?> builder) { toppings = builder.toppings.clone(); // 아이템 50 참조 } }