KnowHow

技術的なメモを中心にまとめます。
検索にて調べることができます。

Python基礎 オブジェクト指向8(Builder) 生成に関するデザインパターン

登録日 :2025/09/28 09:08
カテゴリ :Python基礎

Builderとは

同じ生成手順で異なる材料を使って異なるオブジェクトを生成するパターン

  • 「建築者」が利用者に渡された材料を使って、一連の手順に沿ってオブジェクトを生成する
  • 家を建てるのと同じイメージ

構成要素

Builder

  • インターフェースもしくは抽象クラス
  • オブジェクトの「生成手段」となるAPIを提供する

ConcreteBuilder

  • Builderで提供されるAPIを実装する子クラス
  • 生成したオブジェクトを取得するためのメソッドも提供する

Director

  • 「建築者」の役割を持つクラス
  • Builderクラスで定義されたAPIを使ってオブジェクトを生成する

プロセス
1. ConcreteBuilderのインスタンス化
2. ConcreteBuilderのインスタンスをDirectorに渡す
3. DirectorがConcreteBuilderのメソッドを呼び出して段階的にオブジェクトを生成する
4. ConcreteBuilderから生成されたオブジェクトを受け取る

オブジェクト指向的要素

「継承」「ポリモーフィズム」「移譲」を利用したパターン

  • BuilderとConcreteBuilderは継承(実装)関係
  • DirectorはBuilderのAPIを使って様々なConcreteBuilderを操作することができる
  • DirectorはBuilderのメソッドを呼び出して処理を移譲する

メリット・デメリット

メリット

  • 生成されるオブジェクトの生成過程や生成手段を隠蔽することができる
  • オブジェクト構築用のコードをビジネスロジックから分離することができる

デメリット

  • 複数のクラスを作成する必要があり、過剰な設計となる可能性がある

使い所

  • 生成手順が同じで、詳細が異なるオブジェクトを生成する場合
  • 大量のパラメータをコンストラクタに渡してオブジェクトを生成している場合
    Builderの各工程で必要な値のみを渡すことで、パラメータを小分けにして渡すことができる
    可読性の向上とバグの可能性をていげんさせる

サンプルコード

コンピュータを生成する例

from abc import ABCMeta, abstractmethod


class Computer(object):
    def __init__(self):
        self.type = None
        self.cpu = None
        self.ram = None

    def __str__(self):
        return f"type: {self.type}, cpu: {self.cpu}, ram: {self.ram}"


class ComputerBuilder(metaclass=ABCMeta):
    """Builder"""
    @abstractmethod
    def add_cpu(self, _cpu: str):
        pass

    @abstractmethod
    def add_ram(self, _ram: int):
        pass


class DesktopBuilder(ComputerBuilder):
    """ConcreteBuilder"""
    def __init__(self):
        self.__computer = Computer()
        self.__computer.type = "Desktop"

    def add_cpu(self, _cpu: str):
        self.__computer.cpu = _cpu

    def add_ram(self, _ram: int):
        self.__computer.ram = _ram

    def get_result(self) -> Computer:
        return self.__computer


class LaptopBuilder(ComputerBuilder):
    """ConcreteBuilder"""
    def __init__(self):
        self.__computer = Computer()
        self.__computer.type = "Laptop"

    def add_cpu(self, _cpu: str):
        self.__computer.cpu = _cpu

    def add_ram(self, _ram: int):
        self.__computer.ram = _ram

    def get_result(self) -> Computer:
        return self.__computer


class Director(object):
    def __init__(self, _builder: ComputerBuilder):
        self.__builder = _builder

    def construct(self):
        self.__builder.add_cpu("Core i5")
        self.__builder.add_ram(16)

    def high_pec_construct(self):
        self.__builder.add_cpu("M2")
        self.__builder.add_ram(64)


if __name__ == '__main__':
    desktop_builder = DesktopBuilder()
    desktop_director = Director(desktop_builder)
    desktop_director.construct()
    desktop_computer = desktop_builder.get_result()
    print(desktop_computer)

    laptop_builder = LaptopBuilder()
    laptop_director = Director(laptop_builder)
    laptop_director.high_pec_construct()
    laptop_computer = laptop_builder.get_result()
    print(laptop_computer)