NMP-Study / EffectiveJava2022

Effective Java Study 2022
5 stars 0 forks source link

아이템 2. 생성자에 매개변수가 많다면 빌더를 고려하라 #2

Closed okhee closed 2 years ago

okhee commented 2 years ago

객체 생성에 필요한 매개변수가 많아질 때, 정적 팩토리 & 생성자는 이를 대응하기 어려움 -> Builder를 쓰자

기존 시도 1. 점층적 생성자 패턴

기존 시도 2. JavaBeans 패턴

public static void main() { Article article = new Article(); article.setOid("057"); article.setAid("0001645171"); }

- 객체 생성을 위해 여러 번 메서드 호출이 필요하고, 모든 setter 호출 완료 이전까지 일관성이 무너진 상태로 남는다.
- Immutability를 구현할 수 없다.

### Builder 패턴
- 점층적 생성자 패턴의 안정성과 자바빈 패턴의 가독성을 겸비
- 필수 매개변수만으로 생성자를 호출하여 빌더 객체를 얻어 이를 이용해 객체 생성
- setter 역할 메서드로 매개변수 설정 후, build하여 immutable한 객체 생성

```java
public class Article {
    // ...
    public static class Builder {
        private final String oid;
        private final String aid;
        private String content;

        public Builder(String oid, String aid) {
            this.oid = oid;
            this.aid = aid;
        }

        public Builder content(String content) {
            this.content = content;
            return this;
        }

        public Article build() {
            return new Article(oid, aid, content);
        }
    }
}

@Test
public void articleTest() {
    Article article = new Article.Builder("057", "0001645171")
        .content("지지를 호소했습니다.")
        .build();
    System.out.println(article);
}

Builder 패턴의 단점

계층 구조 ❤️ Builder 패턴

Lombok

// 책 예제와 동일한 결과를 반환
@SuperBuilder
public abstract class Pizza {
    public enum Topping {HAM, MUSHROOM, ONION, PEPPER, SAUSAGE}

    @Singular
    final Set<Topping> toppings;
}

@SuperBuilder
public class Calzone extends Pizza {
    private final boolean sauceInside;
}

@SuperBuilder
public class NyPizza extends Pizza {
    public enum Size {SMALL, MEDIUM, LARGE}
    private final Size size;
}

@Test
public void pizzaTest() {
    NyPizza pizza = NyPizza.builder().size(SMALL)
        .topping(SAUSAGE).topping(ONION).build();
    Calzone calzone = Calzone.builder().topping(HAM)
        .sauceInside(true).build();
}

참고 : Kotlin, DSL 기반 Builder

fun result() = html {
        head {
            title {+"XML encoding with Kotlin"}
        }
        body {
            h1 {+"XML encoding with Kotlin"}
        // ...
        }
    }