- 지난 글에 이어 생성패턴을 다뤄본다.
추상 팩토리 (Abstract Factory)
빌더 (Builder)
팩토리 메서드 (Factory Methods)
프로토타입 (Prototype)
싱글턴 (Singleton)
빌더 (Builder)
- 의도
복잡한 객체를 생성하는 클래스와 표현하는 클래스를 분리하여, 서로 다른 표현이라도 이를 생성할 수 있는 동일한 절차를 제공한다.
- 동기
생성과 표현의 분리를 통한 책임 분리
- 활용성
- 복합 객체의 생성 알고리즘이 이른 합성하는 요소 객체들이 무엇인지 이들의 조립 방법에 독립적일 때
- 합성할 객체들의 표현이 서로 다르더라도 생성 절차에서 이를 지원해야 할 때
- 구조
- 참여자
- Builder: Product 객체의 일부 요소를 생성하기 위한 추상 인터페이스 정의
- ConcreteBuilder: Builder 클래스에 정의된 인터페이스를 구현하며, 제품의 부품들을 모아 빌더를 복합
- 제품 내부 표현을 구축하고 복합 객체가 어떻게 구성되는지에 관한 절차 정의
- Director: Builder 인터페이스를 사용하는 객체를 합성
- Product: 생성할 복합 객체를 표현
- 협력 방법
- 결과
- 제품에 대한 내부 표현을 다양하게 변화할 수 있다.
- Builder에 정의된 추상클래스를 통해 사용자가 동작하기 때문에, 새로운 제품의 표현 방법이나 복합 방법이 바뀔 때 Builder 클래스에서 상속을 통해 새로운 서브클래스를 정의하면 된다.
- 생성과 표현에 필요한 코드를 분리한다.
- 복합 객체를 생성하는 절차를 좀더 세밀하게 나눌 수 있다.
- Director의 통제 아래 하나씩 내부 구성요소들을 만들어 나가기에 생성하는 과정 자체가 반영되어 있다.
- 구현
- 조합과 구축에 필요한 인터페이스를 정의
- 제품에 대한 추상 클래스는 필요없다.
- 제품은 Builder의 서브클래스로 생성되는데, 이 서브클래스 사이에 공통점이 없기 때문이다
- Builder에 있는 메서드의 구현부는 비워둔다.
- 예제
추상 클래스인 PhoneBuilder에서 Director가 요청하는 build 연산을 정의한다.
PhoneBuilder를 상속받은 ConcreteBuilder(AppleBuilder, GalaxyBuilder)가 필요한 표현을 override한다.
ConcreteBuilder는 Phone의 부품들을 조립하고 Director는 조립이 완성된 Phone을 반환한다.
AppleBuilder
Director director = new Director();
AppleBuilder appleBuilder = new AppleBuilder();
director.setPhoneBuilder(appleBuilder);
Phone phone = director.constructPhone();
System.out.println(phone);
Builder
package builder;
import product.Phone;
public abstract class PhoneBuilder {
protected Phone phone;
public Phone getPhone() {
return phone;
}
public PhoneBuilder create() {
phone = new Phone();
return this;
}
public abstract PhoneBuilder buildName();
public abstract PhoneBuilder buildCamera();
public abstract PhoneBuilder buildCPU();
public abstract PhoneBuilder buildDisplay();
}
ConcreteBuilder
package builder;
public class AppleBuilder extends PhoneBuilder {
@Override
public PhoneBuilder buildName() {
toy.setName("Apple");
return this;
}
@Override
public PhoneBuilder buildCamera() {
toy.setCamera("Camera");
return this;
}
@Override
public PhoneBuilder buildCPU() {
toy.setCPU("A12 bionic");
return this;
}
@Override
public PhoneBuilder buildDisplay() {
return this;
}
}
Director
package director;
import builder.PhoneBuilder;
import product.Phone;
public class Director {
private PhoneBuilder phoneBuilder;
public void setPhoneBuilder(PhoneBuilder phoneBuilder) {
this.phoneBuilder = phoneBuilder;
}
public Phone constructPhone() {
return phoneBuilder.create()
.buildName()
.buildCamera()
.buildCPU()
.buildDisplay()
.getPhone();
}
}
Main
import builder.AppleBuilder;
import builder.GalaxyBuilder;
import director.Director;
import product.Phone;
public class Main {
public static void main(String[] args) {
Director director = new Director();
AppleBuilder appleBuilder = new AppleBuilder();
GalaxyBuilder galaxyBuilder = new GalaxyBuilder();
director.setPhoneBuilder(appleBuilder);
Phone iphone = director.constructPhone();
System.out.println(iphone);
director.setPhoneBuilder(galaxyBuilder);
Phone samsungPhone = director.constructPhone();
System.out.println(samsungPhone);
}
}
- 관련 패턴과의 비교
빌더 패턴: 복잡한 객체의 단계별 생성에 중점. 생성 마지막 단계에서 생성한 제품을 반환
추상 팩토리 패턴: 제품의 유사군이 존재할 시 유연한 설계, 만드는 즉시 제품 반환
- 참고 문헌
- GoF의 디자인 패턴(개정판) / 에릭 감마, 리처드 헬름, 랄프 존슨, 존 블라시디스 공저 / 김정아 역 / 프로텍미디어 / 발행 2015년 03월 26일
'theory > 디자인패턴' 카테고리의 다른 글
GoF의 디자인 패턴. 생성패턴 5. 싱글턴 (0) | 2021.09.11 |
---|---|
GoF의 디자인 패턴. 생성패턴 4. 프로토타입 (0) | 2021.09.05 |
GoF의 디자인 패턴. 생성패턴 3. 팩토리 메서드 (0) | 2021.08.22 |
GoF의 디자인 패턴. 생성패턴 1.추상 팩토리 (0) | 2021.08.08 |
GoF의 디자인 패턴. 서론 (0) | 2021.08.01 |