본문 바로가기
Design Pattern/생성 패턴(Creational patterns)

Builder Pattern, 빌더 패턴

by codeyaki 2023. 6. 20.
반응형

빌더 패턴 (Builder Pattern)

빌더 패턴이란?

객체를 단계별로 생성할 수 있게 만들어주는 패턴이다.

 

왜 사용하나요?

  • 생성자의 의미가 좀 더 명확해진다.
  • 재사용을 높인다.
  • 단일 책임의 원칙 (생성만을 담당하는 빌더가 생김)

클래스에 여러 필드들이 있고 생성자에 너무 많은 파라미터를 두게 되면 호출 시에 매우 지저분한 코드가 될 것이다. 또한 파라미터를 부분적으로 사용하지 않는 경우 오버로딩을 통해서 해결할 수 있지만 생성자의 수가 기하급수적으로 늘어나게 될것이다. 빌더 패턴은 이러한 경우에 사용하면 좋은 효과를 볼 수 있다. 

예를 들어 집을 만든다고 했을 때 창문의 형태, 수영장 여부, 크기, 주변 나무 개수, 지붕의 형태, 집의 형태 등등 다양한 조건이 올 수 있다. 이 것을 한 번에 만든다고 하면 아래 코드처럼 관리를 해야 한다.

@Setter
@Getter
@AllArgsConstructor
class House{
    private int WindowType;
    private int doorType;
    private int treeCount;
    private boolean hasSwimpool;
    private boolean hasGarage;
}

class Main{
    static public void main(String[] args){
        House house1 = new House(2, 4, 10, null, true, ...);
        House house2 = new House(1, 1, 2, true, true, ...);
        House house3 = new House(5, 2, 1, null, null, ...);
    
    }
}

이렇게 생성자를 통해서 관리를 하게 되면 인자 하나하나가 무엇을 의미하는지 파악하기도 힘들고 코드를 관리하기도 쉽지 않다.

이때 빌더패턴을 사용하면 해결할 수 있게 된다.

class Main{
    public static void main(String[] args){
        House house1 = House.builder()
                                .windowType(2).doorType(4)
                                .treeCount(10).hasGarage()
                                .build();
        House house2 = House.builder()
                                .windowType(1).doorType(1).treeCount(2)
                                .hasSwimpool().hasGarage()
                                .build();
        House house3 = House.builder()
                                .windowType(5).doorType(2).treeCount(1)
                                .build();
        ...
    
    }
}

이렇게 부품을 조립하듯 한 개 한 개 선택해서 설정할 수 있게 되어 코드만 보더라도 의미를 알 수 있고, 생성자를 오버로딩 하지 않아도 유연한 코드가 된다.

빌더 패턴 만들어보기

class House{
    private int windowType;
    private int doorType;
    private int treeCount;
    private boolean hasSwimpool;
    private boolean hasGarage;
    
    public House(Builder builder){
        this.windowType = builder.windowType;
        this.doorType = builder.doorType;
        this.treeCount = builder.treeCount;
        this.hasSwimpool = builder.hasSwimpool;
        this.hasGarage = builder.hasGarage;
    }
    
    public static class Builder{
        private int windowType;
        private int doorType;
        private int treeCount;
        private boolean hasSwimpool;
        private boolean hasGarage;
        
        public Builder() {};
        
        public Builder windowType(int windowType){
            this.windowType = windowType;
            return this;
        }
        
        public Builder doorType(int doorType){
            this.doorType = doorType;
            return this;
        }
        
        public Builder treeCount(int treeCount){
            this.treeCount = treeCount;
            return this;
        }
        
        public Builder hasSwimpool(){
            this.hasSwimpool = true;
            return this;
        }
        
        public Builder hasGarage(){
            this.hasGarage = true;
            return this;
        }
        
        public House build(){
            return new House(this);
        }
        
    }
}

이와 같이 만들 클래스 안에 static inner 클래스를 통해서 구현을 하면 된다.

 

문제점

보시다시피 코드가 복잡해지게 된다는 단점이 있다.

 

이러한 문제점을 극복하기 위해서 Java에서는 lombok 라이브러리를 사용해서 간편하게 구현할 수 있도록 해 준다.

@Builder
class House{
    private int WindowType;
    private int doorType;
    private int treeCount;
    private boolean hasSwimpool;
    private boolean hasGarage;
}

@Builder 어노테이션을 사용하면 손쉽게 빌드 패턴을 사용하게 해준다. 매우 짱짱 기능 👍🏻

반응형