生成に関するデザインパターン

builder

[6]:
from abc import ABC, abstractproperty, abstractmethod


# 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'メインディッシュ:{self.main_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


class SannmaSetBuilder(SetMealBuilder):
    def __init__(self):
        super().__init__()

    @property
    def product(self):
        return self._set_meal

    def build_main_dish(self):
        self._set_meal.main_dish = "さんま"

    def build_side_dish(self):
        self._set_meal.side_dish = "味噌汁"


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 = "パスタ"

    def build_side_dish(self):
        self._set_meal.side_dish = "スープ"


# ディレクターが外部から呼び出すやつ
class Director(object):
    def __init__(self, builder: SetMealBuilder):
        self.__builder = builder

    @property
    def builder(self):
        return self.__builder

    @builder.setter
    def builder(self, builder):
        self.__builder = builder

    # 食品をビルド
    def build(self):
        self.builder.build_main_dish()
        self.builder.build_side_dish()
        return self.builder


if __name__ == '__main__':
    sannma_builder = SannmaSetBuilder()
    pasta_builder = PastaSetBuilder()

    director = Director(sannma_builder)

    print(director.build().product)

    director = Director(pasta_builder)
    print(director.build().product)

メインディッシュ:さんま,サイドディッシュ:味噌汁
メインディッシュ:パスタ,サイドディッシュ:スープ

factoryメソッド

オブジェクトの生成と具体的な処理を分離することで、柔軟にオブジェクトを利用でき、再利用性を高める。

インターフェースで処理の骨組みを作り、サブクラスを用いてオブジェクトを作成する。サブクラスに応じて、作成されるオブジェクトのタイプを変える

  • Product:生成するオブジェクトの構成要素を定義するインタフェース

  • ConcreteProduct:Productを具体化したクラス

  • Creator:Productを生成する処理を定義したインターフェース

  • ConcreteCreator:Creatorを具体化したConcreteProductを生成する。

[10]:
from abc import ABC, abstractmethod, abstractproperty

# インターフェース作成
class IFactory(ABC):
    def __init__(self):
        self.registered_owners = []

    def create(self, owner):
        self._owner = owner
        product = self._create_product()
        self._register_product(product)
        return product

    @abstractmethod
    def _create_product(self):
        pass

    @abstractmethod
    def _register_product(self, product):
        pass


class CarFatory(IFactory):
    def _create_product(self):
        return Car(self._owner)

    def _register_product(self, product):
        self.registered_owners.append(product.owner)


class ShipFactory(IFactory):
    def _create_product(self):
        return Ship(self._owner)

    def _register_product(self, product):
        self.registered_owners.append(product.owner)


class IProduct(ABC):
    def __init__(self, owner):
        self._owner = owner

    @abstractmethod
    def use(self):
        pass

    @abstractmethod
    def owner(self):
        pass


class Car(IProduct):
    def use(self):
        print(f'{self.owner}:車を運転します')

    @property
    def owner(self):
        return self._owner


class Ship(IProduct):

    def use(self):
        print(f'{self.owner}:船を運転します')

    @property
    def owner(self):
        return self._owner

if __name__ == '__main__':
    car_factory = CarFatory()
    yamada_car = car_factory.create('山田')
    yamada_car.use()

    ship_factory =ShipFactory()
    john_ship=ship_factory.create('John')

    john_ship.use()
    print(ship_factory.registered_owners)

    print(car_factory.registered_owners)
山田:車を運転します
John:船を運転します
['John']
['山田']
[ ]: