-
빌더 패턴(Builder Pattern)이란?Design Pattern/생성 디자인 패턴 2024. 4. 1. 23:15반응형
1. 빌더 패턴이란?
빌더 패턴은 복잡한 객체의 생성 과정과 그 표현 방법을 분리함으로써 동일한 생성 과정에서 서로 다른 표현 결과를 만들 수 있게 하는 디자인 패턴입니다. 이는 객체가 가질 수 있는 여러 옵션들을 명확하게 설정할 수 있게 하며, 최종 객체가 생성될 때까지 변경 불가능(immutable) 상태를 유지할 수 있도록 도와줍니다.
2. 빌더 패턴과 팩토리 패턴의 차이점
빌더 패턴과 팩토리 패턴은 모두 객체 생성을 추상화하는 패턴이지만, 주 사용 시나리오가 다릅니다. 팩토리 패턴은 생성할 객체의 타입이 서브클래스에 의해 결정되는 경우에 사용되며, 주로 객체 생성 로직을 캡슐화할 때 사용됩니다. 반면, 빌더 패턴은 하나의 복잡한 객체를 단계별로 생성해야 할 때 사용되며, 최종적으로 조립하는 방식으로 객체를 생성합니다.
3. Java와 Go로 빌더 패턴을 구현할 때의 차이점
Java는 객체 지향 프로그래밍 언어로, 클래스와 상속을 사용하여 빌더 패턴을 구현합니다. 반면, Go는 인터페이스와 구조체를 활용하는 방식으로 빌더 패턴을 구현하며, 상속보다는 구성(composition)을 선호합니다.
4. 빌더 패턴 예시
Java에서의 빌더 패턴 예시
Java에서 빌더 패턴을 구현할 때는 내부 static 클래스를 사용하여 빌더 역할을 수행하는 것이 일반적입니다.
public class Car { // 필수 매개변수 private final String engine; private final int wheels; // 선택적 매개변수 private final boolean sunroof; private final boolean sportsMode; public static class Builder { // 필수 매개변수 private final String engine; private final int wheels; // 선택적 매개변수 - 기본값으로 초기화 private boolean sunroof = false; private boolean sportsMode = false; public Builder(String engine, int wheels) { this.engine = engine; this.wheels = wheels; } public Builder sunroof(boolean val) { sunroof = val; return this; } public Builder sportsMode(boolean val) { sportsMode = val; return this; } public Car build() { return new Car(this); } } private Car(Builder builder) { engine = builder.engine; wheels = builder.wheels; sunroof = builder.sunroof; sportsMode = builder.sportsMode; } }
Go에서의 빌더 패턴 예시
Go에서는 구조체와 인터페이스를 사용하여 빌더 패턴을 구현합니다. 메소드 체이닝 대신에 함수 옵션 패턴을 사용할 수도 있습니다.
package main type Car struct { Engine string Wheels int Sunroof bool SportsMode bool } type CarBuilder struct { car Car } func NewCarBuilder(engine string, wheels int) *CarBuilder { return &CarBuilder{ car: Car{ Engine: engine, Wheels: wheels, }, } } func (b *CarBuilder) SetSunroof(val bool) *CarBuilder { b.car.Sunroof = val return b } func (b *CarBuilder) SetSportsMode(val bool) *CarBuilder { b.car.SportsMode = val return b } func (b *CarBuilder) Build() Car { return b.car } func main() { car := NewCarBuilder("V8", 4). SetSunroof(true). SetSportsMode(true). Build() fmt.Println(car) }
빌더 패턴을 이해하고 적용하는 것은 객체의 생성과 관리를 훨씬 더 유연하게 만들어 줍니다. 이를 통해 코드의 가독성과 유지보수성을 크게 향상시킬 수 있습니다.
5. 빌더 패턴의 장단점
빌더 패턴의 장점
1. 가독성 향상
빌더 패턴은 매개변수가 많은 객체를 생성할 때, 각 매개변수가 무엇을 의미하는지 명확하게 할 수 있어 코드의 가독성을 크게 향상시킵니다. 메소드 체인을 통해 어떤 옵션을 설정하는지 명확히 알 수 있습니다.
2. 객체 불변성 유지
객체의 모든 매개변수를 한 번에 설정한 후, 객체를 불변(immutable) 상태로 만들 수 있어, 멀티스레드 환경에서의 안정성이 향상됩니다.
3. 유연성과 확장성
빌더 패턴을 사용하면, 객체의 생성 과정에서 조건부 로직을 적용하기 쉬워지며, 미래에 객체에 새로운 매개변수를 추가하거나 기존 매개변수를 변경할 때 유연하게 대응할 수 있습니다.
4. 객체의 일관성 유지
빌더 패턴을 통해 객체가 완전히 생성되기 전까지는 일관성이 없는 상태에 노출되지 않도록 할 수 있으며, 객체의 생성 과정이 완료된 후에만 객체에 접근할 수 있도록 제한할 수 있습니다.
빌더 패턴의 단점
1. 코드 복잡성 증가
빌더 패턴을 구현하려면 추가적인 빌더 클래스를 생성해야 하므로, 간단한 객체에 빌더 패턴을 적용하는 것은 코드의 복잡성만 증가시킬 수 있습니다.
2. 초기 개발 비용 증가
빌더 클래스를 만들고 관리해야 하므로, 단기적으로는 개발 비용과 시간이 증가할 수 있습니다. 복잡한 객체가 아닌 경우, 빌더 패턴의 도입이 오버 엔지니어링으로 이어질 수 있습니다.
3. 성능 저하 가능성
빌더 패턴은 추가적인 객체(빌더 객체)를 생성하므로, 객체 생성 과정에서의 성능 저하가 발생할 수 있습니다. 대부분의 경우 이러한 성능 저하는 미미하지만, 성능이 매우 중요한 어플리케이션에서는 고려해야 할 수 있습니다.
빌더 패턴은 특히 매개변수가 많거나, 설정해야 할 옵션이 많은 복잡한 객체를 생성할 때 매우 유용합니다. 하지만 모든 상황에 빌더 패턴을 적용하는 것은 아니며, 패턴을 도입하기 전에 그 장단점을 잘 고려하여 결정해야 합니다.
반응형'Design Pattern > 생성 디자인 패턴' 카테고리의 다른 글
DI(Dependency Injection)란? (0) 2024.04.11 프로토타입 패턴(Prototype Pattern)이란? (0) 2024.04.02 팩토리 패턴(Factory Pattern)이란? (0) 2024.03.31 싱글턴 패턴(Singleton Pattern)이란? (0) 2024.03.30