Point 2. 생성자에 매개변수가 많은 경우 빌더 고려

방법 1 증분 생성자 패턴

public class Member {

    private String name;                // 필수
    private int age;                       // 필수
    private String address;                // 선택
    private String phone;                // 선택
    private String email;                  // 선택

    // 필수 매개변수를 가지는 생성자
    public Member(String name, int age) {
        this(name, age, null, null, null);
    }

    // 선택 매개변수 address가 추가된 생성자
    public Member(String name, int age, String address) {
        this(name, age, address, null, null);
    }

    // 선택 매개변수 phone이 추가된 생성자
       public Member(String name, int age, String address, String phone) {
        this(name, age, address, phone, null);
    }

    // 모든 매개변수를 가지는 생성자
    public Member(String name, int age, String address, String phone, String email) {
        this.name = name;
        this.age = age;
        this.address = address;
        this.phone = phone;
        this.email = email;
    }
}
//참고 : https://wildeveloperetrain.29

변경하기 번거롭고 읽기 어려운 여러 생성자를 선언하는 방법입니다.

방법 2 JavaBeans 패턴

public void setName(String name) {
    this.name = name;
}

public void setAge(int age) {
    this.age = age;
}

public void setAddress(String address) {
    this.address = address;
}

public void setPhone(String phone) {
    this.phone = phone;
}

public void setEmail(String email) {
    this.email = email;
}
//참고 : https://wildeveloperetrain.29
Member member = new Member();
member.setName("jan");
member.setAge(99);
member.setAddress("KOR");
member.setPhone("01012345678");
//참고 : https://wildeveloperetrain.29

개체가 완전히 설정되기 전에 일관성그것은 무너진다

불변으로 만들 수 없습니다.

방법 3 빌더 패턴

위의 두 가지 방법을 결합하여 장점만 있는 패턴

필수 매개변수는 생성자를 통해 입력됩니다.

생성자 사용의 이점

추가 매개변수는 JavaBeans 패턴(set 메소드 사용)을 사용하여 입력됩니다.

자바빈즈의 장점

set 메서드의 반환 유형을 빌더 자체로 설정합니다.

fluent API , 메서드 연쇄 이렇게 구현

빌더 심화(계층적 클래스 및 빌더)

이해가 안되면 출처 링크로 이동하거나 책을 읽으십시오.

import java.util.*;

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));
          return self();
       }

       // Pizza 를 상속받은 클래스 ( NyPizza , Calzone ) return 
       // 메서드를 구현할 때 NyPizza 와 Calzome의 생성자를 호출하게 된다.

// new NyPizza(this) , new Calzone(this); abstract Pizza build(); // 하위 클래스는 이 메서드를 재정의하고 this를 반환하도록 해야 한다.

protected abstract T self(); } // 저장된 토핑이 build()를 호출할 때 각각 생성자에서 super(builer)를 호출하고 // super는 Pizza의 생성자 이므로 아래의 Pizza가 호출 되면서 토핑을 clone()해서 // 저장한다.

Pizza(Builder<?> builder) { toppings = builder.toppings.clone(); } // 실제 토핑값을 찍어보기 위한 toString() 재정의 @Override public String toString() { Iterator iterator = toppings.iterator(); String returnStr = ""; while(iterator.hasNext()) { returnStr += iterator.next() + ", "; } return returnStr; } }
import java.util.Objects;

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

    public static class Builder extends Pizza.Builder<Builder> {
       private final Size size;

       // NyPizza 는 size를 받는 생성자만 존재함.
       public Builder(Size size) {          
                    super();
          this.size = Objects.requireNonNull(size);
       }

       @Override public NyPizza build() {
          return new NyPizza(this);
       }

       @Override protected Builder self() { return this; }
    }

    private NyPizza(Builder builder) {
       super(builder);
       size = builder.size;
    }
 }

출처: 효과적인 자바
출처 : https://debaeloper.35 (이해가 안되면 이해가 안됨 : 티스토리) See More