Builderパターンは、作成されるオブジェクトと、それを作成するオブジェクトをそれぞれ分けたい場合に用いられる。 同じ作成過程で異なる表現形式の結果を得るために用いる。
例:Vehicle(乗り物)クラス
↓例:Vehicle(乗り物)クラスを継承して
これらのクラスは、Builderインターフェースを前提したコードはそのまま活用することができる。
サブクラスに応じて、作成されるインスタンスの中身を変えることができる。
Product | :作成されるオブジェクト |
Builder | :Productを生成する処理を記述したインターフェース(抽象クラス) |
Create Builder | :Builderの処理を具体化したクラス |
Director | :Builderを利用するクラス |
# 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
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)