Builder 디자인 패턴

Builder 디자인 패턴

DesignPattern
Builder 디자인 패턴
Author

gabriel yang

Published

November 12, 2024

Python에서의 Builder 패턴 설명 및 구현

Builder 패턴은 복잡한 객체 생성 과정을 단계별로 나누어 수행하고, 최종적으로 완성된 객체를 반환하는 디자인 패턴입니다. 일반적으로 생성할 객체가 많은 속성을 가지고 있으며, 생성 과정이 복잡할 때 사용됩니다. Python에서는 이 패턴을 통해 여러 옵션을 가지는 객체를 유연하고 일관되게 구성할 수 있습니다. 이번 글에서는 Builder 패턴을 사용하는 이유와 Python에서 이를 구현하는 방법을 설명하겠습니다.

Builder 패턴을 사용하는 이유

Builder 패턴을 사용하는 주된 이유는 다음과 같습니다:

  1. 복잡한 객체 생성의 단순화: 객체가 여러 속성을 가지고 있고, 각 속성의 값에 따라 객체 생성이 복잡해질 때 Builder 패턴을 사용하여 각 속성을 단계별로 설정할 수 있습니다.

  2. 유연한 객체 구성: 객체 생성 시 선택적인 속성이나 단계가 있을 때, Builder 패턴을 사용하면 특정 속성을 제외하거나, 필요에 따라 추가하는 등 유연하게 객체를 구성할 수 있습니다.

  3. 일관성 유지: 동일한 객체를 여러 곳에서 생성할 때, Builder 패턴을 사용하면 객체 생성의 순서와 구성 방식을 표준화하여 일관성을 유지할 수 있습니다.

  4. 확장성: 새로운 속성을 추가하거나 생성 과정을 변경하는 경우, Builder 클래스의 메서드를 추가하거나 수정하여 손쉽게 확장할 수 있습니다.

Builder 패턴의 구조

Builder 패턴은 다음과 같은 구성 요소를 포함합니다:

  • Product: 생성될 객체입니다.
  • Builder: 객체 생성을 위한 단계별 인터페이스 또는 추상 클래스입니다.
  • ConcreteBuilder: Builder 인터페이스를 구현하여 각 단계별 세부 사항을 설정하는 클래스입니다.
  • Director: Builder를 사용하여 객체를 단계별로 생성하는 역할을 담당합니다.

Python에서의 Builder 패턴 구현 예제

아래 예제에서는 Builder 패턴을 사용하여 자동차(Car) 객체를 생성하는 방법을 보여줍니다. 자동차는 좌석 수, 엔진 유형, GPS 유무 등 여러 옵션을 가지고 있으며, 이를 Builder 패턴으로 쉽게 설정할 수 있습니다.

class Car:
    def __init__(self):
        self.seats = None
        self.engine = None
        self.gps = None

    def __str__(self):
        return f"Car(seats={self.seats}, engine={self.engine}, gps={self.gps})"


class CarBuilder:
    def __init__(self):
        self.car = Car()

    def set_seats(self, number):
        self.car.seats = number
        return self  # 메서드 체이닝을 위해 self 반환

    def set_engine(self, engine_type):
        self.car.engine = engine_type
        return self

    def set_gps(self, gps_enabled):
        self.car.gps = gps_enabled
        return self

    def build(self):
        return self.car


class Director:
    def __init__(self, builder):
        self.builder = builder

    def construct_sports_car(self):
        return (self.builder
                .set_seats(2)
                .set_engine("V8")
                .set_gps(True)
                .build())

    def construct_suv(self):
        return (self.builder
                .set_seats(5)
                .set_engine("V6")
                .set_gps(False)
                .build())

이 코드는 Builder 패턴을 사용하여 Car 객체를 단계적으로 생성하는 방식입니다. Builder 패턴을 사용하면 복잡한 객체를 생성하는 과정을 단순화하고 일관성 있게 관리할 수 있습니다. 각 클래스가 어떤 역할을 수행하는지와 코드의 동작 원리를 단계별로 설명하겠습니다.

1. Car 클래스 (Product)

class Car:
    def __init__(self):
        self.seats = None
        self.engine = None
        self.gps = None

    def __str__(self):
        return f"Car(seats={self.seats}, engine={self.engine}, gps={self.gps})"
  • Car 클래스는 생성될 객체로, 자동차의 속성을 정의합니다.
  • self.seats, self.engine, self.gps 속성은 각각 좌석 수, 엔진 종류, GPS 여부를 나타냅니다.
  • __str__ 메서드는 Car 객체의 정보를 문자열로 반환하여, 객체를 쉽게 확인할 수 있게 해줍니다.

2. CarBuilder 클래스 (Builder)

class CarBuilder:
    def __init__(self):
        self.car = Car()
  • CarBuilder 클래스는 Car 객체를 구성하는 빌더 역할을 합니다.
  • self.car = Car()Car 객체를 초기화하여 빌더가 자동차 객체의 속성을 단계적으로 설정할 수 있게 합니다.
    def set_seats(self, number):
        self.car.seats = number
        return self  # 메서드 체이닝을 위해 self 반환
  • set_seats 메서드는 Car 객체의 seats 속성을 설정합니다.
  • 메서드가 self를 반환함으로써 메서드 체이닝을 지원하여, 여러 설정을 순차적으로 호출할 수 있습니다.
    def set_engine(self, engine_type):
        self.car.engine = engine_type
        return self
  • set_engine 메서드는 Car 객체의 engine 속성을 설정합니다.
    def set_gps(self, gps_enabled):
        self.car.gps = gps_enabled
        return self
  • set_gps 메서드는 Car 객체의 gps 속성을 설정합니다.
    def build(self):
        return self.car
  • build 메서드는 최종적으로 완성된 Car 객체를 반환합니다.
  • CarBuilder를 사용하여 설정한 속성들을 포함한 Car 객체가 반환됩니다.

3. Director 클래스

class Director:
    def __init__(self, builder):
        self.builder = builder
  • Director 클래스는 CarBuilder 인스턴스를 받아 특정 설정에 맞는 Car 객체를 구성하는 역할을 합니다.
    def construct_sports_car(self):
        return (self.builder
                .set_seats(2)
                .set_engine("V8")
                .set_gps(True)
                .build())
  • construct_sports_car 메서드는 스포츠카를 구성합니다.
  • set_seats(2), set_engine("V8"), set_gps(True)를 통해 2인승, V8 엔진, GPS가 있는 스포츠카를 생성합니다.
  • 마지막에 build()를 호출하여 완성된 Car 객체를 반환합니다.
    def construct_suv(self):
        return (self.builder
                .set_seats(5)
                .set_engine("V6")
                .set_gps(False)
                .build())
  • construct_suv 메서드는 SUV를 구성합니다.
  • set_seats(5), set_engine("V6"), set_gps(False)를 통해 5인승, V6 엔진, GPS가 없는 SUV를 생성합니다.
  • 최종적으로 build()를 호출하여 구성된 Car 객체를 반환합니다.

사용 예제

builder = CarBuilder()
director = Director(builder)

sports_car = director.construct_sports_car()
print(sports_car)  # 출력: Car(seats=2, engine=V8, gps=True)

suv = director.construct_suv()
print(suv)  # 출력: Car(seats=5, engine=V6, gps=False)
  • CarBuilder 인스턴스를 생성하여, Director가 빌더를 사용하도록 합니다.
  • construct_sports_carconstruct_suv를 호출하여 각각의 설정에 맞는 Car 객체를 생성하고 출력합니다.

Builder 패턴의 장점

  • 유연성: 각 속성을 메서드 체이닝으로 설정할 수 있어 원하는 속성만 선택적으로 적용 가능
  • 확장성: 추가 속성을 쉽게 추가할 수 있어 유지보수가 용이
  • 재사용성: 동일한 빌더를 여러 객체에 재사용 가능
  • 코드 가독성: 객체 생성 코드가 일관되어 가독성이 높아짐

Builder 패턴 다이어그램

다음은 Builder 패턴을 시각적으로 설명하는 UML 다이어그램입니다.

classDiagram
    class Car {
        -int seats
        -str engine
        -bool gps
        +__str__()
    }

    class CarBuilder {
        -Car car
        +set_seats(int): CarBuilder
        +set_engine(str): CarBuilder
        +set_gps(bool): CarBuilder
        +build(): Car
    }

    class Director {
        -CarBuilder builder
        +construct_sports_car(): Car
        +construct_suv(): Car
    }

    Car <-- CarBuilder
    CarBuilder <-- Director

결론

Builder 패턴은 Python에서 복잡한 객체 생성 과정을 단순화하고 유연하게 만드는 데 유용한 패턴입니다. 특히 선택적이거나 설정 가능한 속성이 많은 객체를 생성할 때, 이 패턴을 통해 생성 과정을 단계별로 나누어 일관된 객체를 얻을 수 있습니다.

카테고리 다른 글

Date Title Author
Jan 1, 3000 전체 카테고리 gabriel yang
Nov 25, 2024 Python 전략 패턴 gabriel yang
Nov 25, 2024 Python 옵저버 패턴 gabriel yang
Nov 23, 2024 Python 데코레이터 패턴 gabriel yang
Nov 11, 2024 싱글톤 디자인 패턴 gabriel yang
Sep 25, 2024 디자인패턴 선택 기준 gabriel yang
Sep 25, 2024 자주사용되는 디자인패턴 1 gabriel yang
Sep 25, 2024 자주사용되는 디자인패턴 2 gabriel yang
No matching items
Back to BLOG LIST