본문으로 바로가기
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.



복잡한 객체의 생성 과정과 표현 방법을 분리하여 동일산 생성 절차에서 서로 다른 표현 결과를 만들 수 있게 하는 패턴이다. 빌더 패턴은 팩토리 패턴 또는 추상 팩토리 패턴과 매우 비슷하다. 빌더 패턴도 새로운 객체를 만들어서 반환하는 패턴이긴 하지만 실제 동작 방식은 조금 다르다고 할 수 있다. 빌더 패턴은 생성자에 들어갈 매개 변수가 많든 적든 차례차례 매개 변수를 받아들이고 모든 매개 변수를 받은 뒤에 이 변수들을 통합해서 한번에 사용한다.


아무리 말로 설명해도 왜 필요한지 쉽게 설명할 수 있는 한가지의 예가 있다. 


아래 사람의 정보가 있다. 사람 정보에는 이름, 나이, 성별, 핸드폰번호, 주소, 직업 등등이 있는데 객체를 생성할 때 인자의 값을 잘못 주게 된다면 잘못된 정보가 저장될 수 있다. 예를 들어 이름이 들어갈 파라미터에 나이가 들어갈 수가 있다. 또한 가독성도 좋지 않다. 복잡하고 클래스에 Javadoc으로 만들어서 설명을 잘 해놔야한다. 근데 그렇게 하는 사람 몇 없다. 빌더패턴은 이런 단점을 보완하는 명시적이고 직관적으로 객체를 생성하고 반환할 수 있게 도와준다.


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
32
33
34
35
36
37
class Person {
    private String name;
    private String age;
    private String sex;
    private String phoneNumber;
    private String address;
    private String job;
    
    public Person(String name) {
        this(name, "");
    }
    
    public Person(String name, String age) {
        this(name, age, "");
    }
    
    public Person(String name, String age, String sex) {
        this(name, age, sex, "");
    }
    
    public Person(String name, String age, String sex, String phoneNumber) {
        this(name, age, sex, phoneNumber, "");
    }
    
    public Person(String name, String age, String sex, String phoneNumber, String address) {
        this(name, age, sex, phoneNumber, address, "");
    }
    
    public Person(String name, String age, String sex, String phoneNumber, String address, String job) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.phoneNumber = phoneNumber;
        this.address = address;
        this.job = job;
    }
}



빌더 패턴을 적용해보자. 빌더 패턴을 위해 다시 Person 클래스를 생성자 1개만 남기는 것으로 수정을 하였다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Person {
    private String name;
    private String age;
    private String sex;
    private String phoneNumber;
    private String address;
    private String job;
    
    public Person(String name, String age, String sex, String phoneNumber, String address, String job) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.phoneNumber = phoneNumber;
        this.address = address;
        this.job = job;
    }
 
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", sex=" + sex + ", phoneNumber=" + phoneNumber + ", address=" + address + ", job=" + job + "]";
    }
}



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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class PersonBuilder {
    private String name;
    private String age;
    private String sex;
    private String phoneNumber;
    private String address;
    private String job;
    
    
    public PersonBuilder setName(String name) {
        this.name = name;
        
        return this;
    }
    
    public PersonBuilder setAge(String age) {
        this.age = age;
        
        return this;
    }
    
    public PersonBuilder setSex(String sex) {
        this.sex = sex;
        
        return this;
    }
    
    public PersonBuilder setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
        
        return this;
    }
    
    public PersonBuilder setAddress(String address) {
        this.address = address;
        
        return this;
    }
    
    public PersonBuilder setJob(String job) {
        this.job = job;
        
        return this;
    }
    
    public Person build() {
        Person person = new Person(name, age, sex, phoneNumber, address, job);
        
        return person;
    }
}



Main 함수 


1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
    PersonBuilder personBuilder = new PersonBuilder();
    
    Person ktko = personBuilder.setName("ktko").setAge("30").setSex("Male").setJob("Programmer").setAddress("Seoul").build();
    System.out.println(ktko.toString()); //Person [name=ktko, age=30, sex=Male, phoneNumber=null, address=Seoul, job=Programmer]
    
    Person yjs = personBuilder.setName("yjs").setAge("30").setSex("FeMale").setJob("Designer").build();
    System.out.println(yjs.toString()); //Person [name=yjs, age=30, sex=FeMale, phoneNumber=null, address=null, job=Designer]
}



빌더 패턴을 적용해보니 엄청나게 깔끔해졌다. 불필요한 생성자를 만들지 않고 깔끔하게 객체를 만들 수 있으며 데이터 순서와 상관 없이 객체를 만들 수 있고, 생성자 필드를 보거나, JavaDoc을 볼 필요 없이 직관적이고 명시적인 setter 메서드 이름으로 데이터를 추가하여 객체를 만들 수 있다. 반환된 객체에 setter 함수가 없다면 변경불가능한 객체가 될 수 있고 setter 함수가 있다면 변경도 가능한 객체가 될 수 있다.


빌더 패턴은 Effective Java 규칙2에 포함된 중요한 내용이다. 링크로 가서 규칙2에 대한 내용을 보길 바란다. 위의 예제와 같은 주제지만 구현을 다르게 했기 때문에 보는 것이 좋을 것 같다.