복잡한 객체의 생성 과정과 표현 방법을 분리하여 동일산 생성 절차에서 서로 다른 표현 결과를 만들 수 있게 하는 패턴이다. 빌더 패턴은 팩토리 패턴 또는 추상 팩토리 패턴과 매우 비슷하다. 빌더 패턴도 새로운 객체를 만들어서 반환하는 패턴이긴 하지만 실제 동작 방식은 조금 다르다고 할 수 있다. 빌더 패턴은 생성자에 들어갈 매개 변수가 많든 적든 차례차례 매개 변수를 받아들이고 모든 매개 변수를 받은 뒤에 이 변수들을 통합해서 한번에 사용한다.
아무리 말로 설명해도 왜 필요한지 쉽게 설명할 수 있는 한가지의 예가 있다.
아래 사람의 정보가 있다. 사람 정보에는 이름, 나이, 성별, 핸드폰번호, 주소, 직업 등등이 있는데 객체를 생성할 때 인자의 값을 잘못 주게 된다면 잘못된 정보가 저장될 수 있다. 예를 들어 이름이 들어갈 파라미터에 나이가 들어갈 수가 있다. 또한 가독성도 좋지 않다. 복잡하고 클래스에 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에 대한 내용을 보길 바란다. 위의 예제와 같은 주제지만 구현을 다르게 했기 때문에 보는 것이 좋을 것 같다.
'자바 디자인 패턴' 카테고리의 다른 글
디자인 패턴 - 팩토리 메서드 패턴(Factory Method Pattern) (0) | 2018.10.15 |
---|---|
디자인 패턴 - 템플릿 메서드 패턴(Template Method Pattern) (0) | 2018.10.15 |
디자인 패턴 - 싱글턴 패턴(Singleton Pattern) (0) | 2018.10.15 |
디자인 패턴 - 데코레이터 패턴(Decorator Pattern) (0) | 2018.10.12 |
디자인 패턴 - 프록시 패턴(Proxy Pattern) (0) | 2018.10.12 |