티스토리 뷰

반응형

Builder Pattern

1. GoF 디자인 패턴

복잡한 객체를 생성하는 방법과 표현하는 방법을 정의하는 클래스를 별도로 분리하여, 서로 다른 표현이라도 이를 생성할 수 있는 동일한 절차를 제공할 수 있도록 합니다.

활용성
- 복합 객체의 생성 알고리즘이 이를 합성하는 요소 객체들이 무엇인지 이들의 조립 방법에 독립적일 때
- 합성할 객체들의 표현이 서로 다르더라도 생성 절차에서 이를 지원해야 할 때

 

2. Effective Java

생성자에 매개변수가 많다면 빌더를 고려하라

일반적인 정적 팩터리와 생성자는 점층적 생성자 패턴으로 해결할 수 있지만, 매개변수가 많아지면 클라이언트 코드를 작성하거나 읽기 어려워진다.

자바빈즈 패턴(setXxxx() 형식으로 작성하는 형식)에서는 객체 하나를 만들려면 메서드를 여러 개 호출해야 하고, 객체가 완전히 생성되기 전까지는 일관성(consistence)이 무너진 상태에 놓이게 된다.

빌더 패턴은 (파이썬과 스칼라에 있는) 명명된 선택적 매개변수(named optional parameters)를 흉내 낸 것이다.

 

 

1. Java의 예시

일반적으로 스프링부트에서 객체를 만들때에는 @Builder 패턴을 주로 붙여서 쓰인다. 하지만 실제로 어떻게 만들어야 할지 잘 몰랐던 나는 어떻게 구현해야 할까 고민하다 이렇게 정리하는 김에 글을 쓰기로 했다.

 

위의 인용을 보시면 아시겠지만 매개변수가 많거나 선택적 매개변수를 써야할 상황이 많을 경우 이를 해결할 방법으로 주로 쓰이는 생성패턴 방식이다.

 

public class Mac {
    private final String display;
    private final int cpu;
    private final int ram;
    private final int ssd;
    private final boolean preInstalledSoftware;

    public static class Builder{
        private final String display;
        private int cpu = 1;
        private int ram = 16;
        private int ssd = 1;
        private boolean preInstalledSoftware = false;

        private Builder(String display){
            this.display = display;
        }

        public Builder cpu(int val){
            cpu = val;
            return this;
        }

        public Builder ram(int val){
            ram = val;
            return this;
        }

        public Builder ssd(int val){
            ssd = val;
            return this;
        }

        public Builder preInstalledSoftware(boolean val){
            preInstalledSoftware = val;
            return this;
        }

        public Mac build(){
            return new Mac(this);
        }

    }

    private Mac(Builder builder){
        assert builder.display!=null;
        this.display=builder.display;
        this.cpu = builder.cpu;
        this.ram = builder.ram;
        this.ssd = builder.ssd;
        this.preInstalledSoftware = builder.preInstalledSoftware;
    }

    public static Builder builder(String display){
        return new Builder(display);
    }

    @Override
    public String toString() {
        return "display: "+ display +", cpu: " + cpu+", ram: "+ram+", ssd: "+ssd+", preInstalledSoftware: "+preInstalledSoftware;
    }
}

예시는 맥북 옵션을 선택하는 것에 대하여 짜봤다.

private Builder(String display){
            this.display = display;
        }
public static Builder builder(String display){
        return new Builder(display);
    }

 

해당 부분을 프라이빗으로 건 이유는 "new Mac.Builder()"와 같이 사용하는 것을 막기 위해 시도하였다. 스프링부트에서 제공하는 @Builder를 썼을 때 보통 "Mac.builder().display().~~" 와 같이 사용했던 경험이 있어서 이와 비슷하게 따라해봤다.

 

위의 빌더 패턴과 다른 점이 있다면 필수적으로 받아야 하는 값을 "builder(display)"와 같이 작성했다는 것이다.

(롬북에서 지원해주는 @Builder는 초기화 값을 null로 해준다.)

 

이에 대한 테스트를 실시해봤다.

public class SimpleTest {
    @Test
    void test_Builder패턴(){
        String display= "16inch";
        Mac mac = Mac.builder(display).build();
        System.out.println(mac);
    }
}

결과는 성공! 

 

 

2. Python

class Mac:
    def __init__(self, display, cpu=1, ram=16, ssd=1, pre_installed_software=False):
        self.__display=display
        self.__cpu = cpu
        self.__ram = ram
        self.__ssd = ssd
        self.__pre_installed_software = pre_installed_software

    @property
    def display(self):
        return self.__display

    @property
    def cpu(self):
        return self.__cpu

    @property
    def ram(self):
        return self.__ram

    @property
    def ssd(self):
        return self.__ssd

    @property
    def pre_installed_software(self):
        return self.__pre_installed_software

    def __str__(self):
        return f'display: {self.__display}, cpu: {self.__cpu}, ram: {self.__ram}, ssd: {self.__ssd}, pre_installed_software: {self.__pre_installed_software}'

 

위에서 자바 이팩티브에 있던 선택적 매개변수라는 것은 

mac= Mac(display="16inch", ram=32)

와 같이 "key=value" 형식으로 작성하는 것을 의미한다. 

위의 파이썬 코드는 자바와 동일한 기능을 한다. 만일 display의 값을 명시하지 않는다면 에러를 내게 된다.

 

이렇게 자바의 빌더패턴은 파이썬의 선택적 매개변수를 흉내낸 것으로 볼 수 있다.

 

참고: GoF 디자인패턴, Java Effective

반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함