이펙티브 자바 2

참치돌고래·2021년 8월 29일
0

이펙티브 자바

목록 보기
2/21

생성자 매개변수가 많은 경우에 빌더 사용을 고려해보자.

1. 생성자

매개변수를 최소한으로 사용하는 생성자를 사용해서 인스턴스를 생성할 수 있다.

public class NutritionFacts{
	public NutritionFacts(int ServingSize, int ~){
    
    	this.ServingSize = ServingSize;
        this~ = ~;
        ~~
    
    }
	public static void main(String[] args){
		NutritionFacts cocaCola = new NutritionFacts(240,8,100,0,35,7);    
	}

}

필요없는 매개변수도 넘겨야 하는 경우가 발생하는데, 보통 0 같은 기본값을 넘긴다.

2.자바빈

아무런 매개변수를 받지 않는 생성자를 사용해서 인스턴스를 만들고, 세터를 통해 필요한 필드만을 설정한다.
(기본 생성자 생성 후, setter 모두 생성)

NutritionFacts cocaCola = new NutritionFacts();
cocaCola.setServingSize(240);
cocaCola.setCalories(8);
cocaCola.setSodium(35);
cocaCola.setCarbohydrate(27);

원하는 인스턴스를 만들기까지 여러번의 호출을 거친다.
자바빈이 중간에 사용되는 경우 안정적이지 않은 상태로 사용될 여지가 있으며, 불변 클래스로 만들지 못하는 경우도 있다.

  • freeze를 통해 객체를 얼릴 수있다 -> 불변화 된 객체로 만들어 반환

3.빌더

빌더 패턴은 만들려는 객체를 생성하지 않고, 클라이언트는 빌더에 필수적인 매개변수를 주면서 호출해 빌더 객체를 얻은 다음 빌더 객체가 제공하는 메소드를 사용해서 부가적인 필드들을 채워넣고 최종적으로 메소드를 호출해서 객체를 생성합니다.

	NutritionFacts cocaCola = new NutritionFacts.Builder(240,8) 
                                                    .calories(100)
                                                    .sodium(35)
                                                    .carbohydrate(27)
                                                    .build();
                               

빌의 생성자난 메소드에서 유효성을 확인할 수 있다. 검증에 실패하면 IllegalArgumentException을 던지고 에러 메세지로 어떤 매개변수가 잘못됐는지 알려줄 수 있다.

빌더 패턴은 계층적으로 설계된 클래스와 함께 쓰기에 좋다.
추상 클래스 = 추상 빌더
구체 클래스 = 구체 빌더

public abstract class Pizza{
	public enum Topping{ HAM, MUSHROOM, ONION }
    
    final EnumSet<Topping> toppings;
    
    abstract static class Builder<T extends Builder<T>>{
    	EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class)
        
        public T addTopping(Topping topping){
        	toppings.add(Object.requireNonNull((topping));
            return self();
        }
        
        abstract Pizza build();
        protected abstract T self();
        
    }
    
    Pizza(Builder<?> builder){
    	toppings = builder.toppings;
    }
    
}
 public class MYPizza extends Pizza{
 	public enum Size { Small, Medium, Large}
    	private final Size size;
        
        public static class Builder extends Pizza.Builder<Builder>{
        	private final Size size;
            
            public Builder(Size size){
            	this.size = Objects.requireNonNull(size)
            }
            
            @Override
            public MyPizza build(){
            	return new MyPizza(this);
            }
            @Override
            protected Builder self(){
            	return this;
            }
        }
        private MyPizza(Builder builder){
        	super(builder);
            	size = builder.size;
        }
 }

client 코드


public class PizzaClient{
	public static void main(String[] args){
    	MyPizza myPizza = new MyPizza.Builder(MyPizza.Size.MEDIUM)
                                    .addTopping(Pizza.Topping.HAM)
                                    .build();
        
    }
}

클라이언트 코드는 간단하지만, 구현 코드는 장황해질 수 있다.

@Builder를 통해 빌더 패턴 적용

Lombok의 Builder 어노테이션을 통해 간단한 빌더 패턴을 생성할 수 있다.

  • @Singular, @Default
profile
안녕하세요

0개의 댓글