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)