Builder 패턴의 개요
Builder 패턴은 객체 생성을 유연하고 직관적으로 만들기 위한 디자인 패턴입니다. 이 패턴은 복잡한 객체의 생성 과정을 추상화하고, 사용자가 단계별로 객체를 구성할 수 있게 합니다.
Builder 패턴은 다음과 같은 요소로 구성됩니다:
- Director: 객체 생성을 담당하며, Builder 인터페이스를 사용하여 객체를 구성합니다.
- Builder: 객체 생성을 위한 인터페이스를 정의하고, 객체의 각 부분을 구성하는 메서드를 제공합니다.
- ConcreteBuilder: Builder 인터페이스를 구현하여 객체를 구성하는 역할을 합니다.
- Product: 생성할 객체의 표현입니다.
// Product 클래스
public class Product {
private String partA;
private String partB;
private String partC;
public void setPartA(String partA) {
this.partA = partA;
}
public void setPartB(String partB) {
this.partB = partB;
}
public void setPartC(String partC) {
this.partC = partC;
}
public String getResult() {
return "Part A: " + partA + ", Part B: " + partB + ", Part C: " + partC;
}
}
// Builder 인터페이스
public interface Builder {
void buildPartA();
void buildPartB();
void buildPartC();
Product getResult();
}
// ConcreteBuilder 클래스
public class ConcreteBuilder implements Builder {
private Product product;
public ConcreteBuilder() {
this.product = new Product();
}
public void buildPartA() {
product.setPartA("A");
}
public void buildPartB() {
product.setPartB("B");
}
public void buildPartC() {
product.setPartC("C");
}
public Product getResult() {
return product;
}
}
// Director 클래스
public class Director {
private Builder builder;
public void setBuilder(Builder builder) {
this.builder = builder;
}
public Product construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
return builder.getResult();
}
}
// 예제 코드 사용
public class Main {
public static void main(String[] args) {
Director director = new Director();
Builder builder = new ConcreteBuilder();
director.setBuilder(builder);
Product product = director.construct();
System.out.println(product.getResult());
}
}
위의 예제 코드에서 Builder 패턴을 사용하여 Product
객체를 생성하고 구성합니다. Builder
인터페이스는 객체 생성을 위한 메서드를 정의하고, ConcreteBuilder
클래스는 해당 인터페이스를 구현하여 실제 객체를 생성하고 구성합니다. Director
클래스는 Builder
인터페이스를 사용하여 객체 생성 과정을 조정하고, 최종적으로 Product
객체를 반환합니다.
이 예제 코드는 Builder 패턴의 기본적인 구현을 보여줍니다. 각 부분을 적절히 확장하고, 객체의 유효성 검사를 추가하여 실제 프로덕션 환경에서 사용할 수 있는 완전한 Builder 패턴을 구현할 수 있습니다.
Builder 패턴의 장점
Builder 패턴은 다음과 같은 장점을 가집니다:
- 객체의 생성 과정을 단계적으로 수행하므로, 객체의 구성이 명확하고 유연합니다.
- 복잡한 객체를 생성할 때, 가독성이 높은 코드를 작성할 수 있습니다.
- 객체 생성 과정에 대한 의존성을 외부로 노출시키지 않으므로, 객체의 일관성과 안정성을 보장합니다.
Builder 패턴을 쓸 때 주의해야 할 점
Builder 패턴을 사용할 때 주의해야 할 점은 다음과 같습니다:
- 객체의 생성 과정을 단계적으로 수행하기 때문에, 객체의 일부 구성 요소가 유효하지 않은 상태로 사용될 수 있습니다. 이를 방지하기 위해 객체의 유효성 검사를 수행해야 합니다.
- Builder 패턴은 일반적으로 복잡한 객체 생성에 사용되지만, 단순한 객체에는 비효율적일 수 있습니다. 객체의 구성 단계가 많거나 복잡하지 않은 경우에는 다른 생성 패턴을 고려해야 합니다.
다음은 단순한 객체의 생성에 Builder 패턴을 사용하여 비효율적인 예제 코드입니다:
public class SimpleObject {
private String propertyA;
private String propertyB;
private String propertyC;
public SimpleObject(String propertyA, String propertyB, String propertyC) {
this.propertyA = propertyA;
this.propertyB = propertyB;
this.propertyC = propertyC;
}
// Getters and setters
}
public class SimpleObjectBuilder {
private String propertyA;
private String propertyB;
private String propertyC;
public SimpleObjectBuilder() {
}
public SimpleObjectBuilder setPropertyA(String propertyA) {
this.propertyA = propertyA;
return this;
}
public SimpleObjectBuilder setPropertyB(String propertyB) {
this.propertyB = propertyB;
return this;
}
public SimpleObjectBuilder setPropertyC(String propertyC) {
this.propertyC = propertyC;
return this;
}
public SimpleObject build() {
return new SimpleObject(propertyA, propertyB, propertyC);
}
}
public class Main {
public static void main(String[] args) {
SimpleObjectBuilder builder = new SimpleObjectBuilder();
SimpleObject simpleObject = builder.setPropertyA("A")
.setPropertyB("B")
.setPropertyC("C")
.build();
}
}
위의 예제 코드에서는 단순한 객체인 SimpleObject
를 생성하는 데 Builder 패턴을 사용하였습니다. 그러나 SimpleObject
클래스의 생성자에 이미 필요한 속성들을 받아 초기화할 수 있는 방법이 제공되므로, Builder 패턴을 사용하는 것은 비효율적입니다. 객체의 생성에 불필요한 중간 단계인 SimpleObjectBuilder
를 거치므로 코드가 더 복잡해지고 가독성이 떨어집니다.
효율적인 방법은 다음과 같이 바로 SimpleObject
객체를 생성하는 것입니다:
public class Main {
public static void main(String[] args) {
SimpleObject simpleObject = new SimpleObject("A", "B", "C");
}
}
이렇게 하면 불필요한 Builder 클래스를 사용하지 않고도 단순한 객체를 직접 생성할 수 있습니다.
Builder 패턴과 함께 사용되는 다른 패턴
Builder 패턴은 다른 디자인 패턴과 함께 사용될 수 있습니다. 자주 함께 사용되는 패턴들은 다음과 같습니다:
- 추상 팩토리(Abstract Factory) 패턴: 추상 팩토리 패턴을 사용하여 여러 종류의 Builder 인터페이스를 생성하고, 각 Builder 인터페이스에 대응하는 ConcreteBuilder를 사용하여 다양한 종류의 객체를 생성할 수 있습니다.
- 프로토 타입(Prototype) 패턴: 프로토 타입 패턴을 사용하여 기존의 객체를 복제하고, Builder 패턴을 사용하여 복제된 객체를 수정하거나 추가 구성할 수 있습니다.
- 일관된 인터페이스(Uniform Interface) 패턴: Builder 패턴을 사용하여 여러 객체를 생성할 때, 일관된 인터페이스를 사용하여 객체를 생성하고 구성할 수 있습니다.