nonoのポートフォリオサイト

デザインパターン Builder

デザインパターンの一つであるBuilder Pattern

Builderパターンは、作成されるオブジェクトと、それを作成するオブジェクトをそれぞれ分けたい場合に用いられる。 同じ作成過程で異なる表現形式の結果を得るために用いる。


Builderインターフェース(抽象クラス:具体的な処理を書く前の設計書のようなもの)

例:Vehicle(乗り物)クラス

Builderインターフェースを継承した、具体的なクラスを作成

例:Vehicle(乗り物)クラスを継承して

  1. CarBuilder
  2. BusBuilder
  3. TruckBuilder

これらのクラスは、Builderインターフェースを前提したコードはそのまま活用することができる。
サブクラスに応じて、作成されるインスタンスの中身を変えることができる。

構成要素

Product :作成されるオブジェクト
Builder :Productを生成する処理を記述したインターフェース(抽象クラス)
Create Builder :Builderの処理を具体化したクラス
Director :Builderを利用するクラス

サンプルコード

SetMealBuilderという抽象クラスを使って、いろいろな料理クラスを作成します。


    # Builderパターン
    from abc import ABC, abstractmethod, abstractproperty
    
    
    # Product
    class SetMeal(object):
    
        @property
        def main_dish(self):
            return self.__main_dish
    
        @main_dish.setter
        def main_dish(self, main_dish):
            self.__main_dish = main_dish
    
        @property
        def side_dish(self):
            return self.__side_dish
    
        @side_dish.setter
        def side_dish(self, side_dish):
            self.__side_dish = side_dish
    
        def __str__(self):
            return f'main dish:{self.main_dish}, side dish:{self.side_dish}'
    
    
    # Builderのインターフェース
    class SetMealBuilder(ABC):
    
        def __init__(self):
            self._set_meal = SetMeal()
    
        @abstractproperty
        def product(self):
            pass
    
        @abstractmethod
        def build_main_dish(self):
            pass
    
        @abstractmethod
        def build_side_dish(self):
            pass
    
    
    # Builderインターフェースを継承した詳細クラスの作成
    class SalmonSetBuilder(SetMealBuilder):
    
        def __init__(self):
            # 親クラスのコンストラクタを継承(実行)する
            super().__init__()
    
        @property
        def product(self):
            return self._set_meal
    
        def build_main_dish(self):
            self._set_meal.main_dish = 'Salmon'
            return self
    
        def build_side_dish(self):
            self._set_meal.side_dish = 'Miso Soup'
            return self
    
    
    class PastaSetBuilder(SetMealBuilder):
    
        def __init__(self):
            super().__init__()
    
        @property
        def product(self):
            return self._set_meal
    
        def build_main_dish(self):
            self._set_meal.main_dish = 'Pasta'
            return self
    
        def build_side_dish(self):
            self._set_meal.side_dish = 'Soup'
            return self
    
    
    # Director (外部から抽象クラスを呼び出すクラス)
    # あくまで抽象クラスに依存する(依存性逆転の原則)
    class Director(object):
    
        def __init__(self, set_meal_builder: SetMealBuilder):
            self.__builder = set_meal_builder
    
        @property
        def builder(self):
            return self.__builder
    
        @builder.setter
        def builder(self, builder: SetMealBuilder):
            self.__builder = builder
    
        def build(self):
            # self.builder.build_main_dish()
            # self.builder.build_side_dish()
            # 以下のように1行で書くこともできる
            self.builder.build_main_dish().build_side_dish()
            return self.builder

Builderパターンを実行しています。


    if __name__ == '__main__':
        """作成したBuilderパターンを使用してみよう"""
        salmon_builder = SalmonSetBuilder()
        pasta_builder = PastaSetBuilder()
    
        director = Director(salmon_builder)
        # director.builder() -> spel miss builder=>build
        print(director.build().product)
    
        director = Director(pasta_builder)
        print(director.build().product)