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

デザインパターン Factory

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

工場のように大量の製品を作成するときのデザインパターン

  1. 製品側と工場側で分けて考えて、工場側でテンプレートを作成する。
  2. テンプレートに応じて、工場を作成して、各上場で製品を作成する。

イメージ

工場 → 船工場 → 船作成
   → 車工場 → 車作成

目的

オブジェクトの生成とオブジェクトの具体的な処理を分離することで、
柔軟にオブジェクトを利用でき、再利用性を高める。(単一責任の原則を満たす)

仕組み

インターフェース(抽象クラス)で処理の骨組みを作り(工場)、サブクラスを用いてオブジェクトを作成する
サブクラスに応じて、作成されるオブジェクトのタイプを変える(船工場から船作成)


構成要素

インターフェースの分離、依存性逆転の原則、などを満たしているものと考えられる

Product :作成するオブジェクトの構成要素を定義するインターフェース(抽象クラス):工場の構成要素の原型
ConcreteProduct :Productを具体化したクラス(複数作成):船工場、車工場、飛行機工場、、、
Creator :Productを生成する処理を定義したインターフェース(抽象クラス):工場の処理の原型
ConcreteCreator :Creatorを具体化したConcreteProductを作成するクラス:船、車、、、

サンプルコード

:Creator(工場の設計図)の定義をします


from abc import ABC, abstractmethod, abstractproperty

# Creator
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

Creatorの具体的な処理を、ConcreteCreatorにて定義します。


# ConcreteCreator
class CarFactory(IFactory):
    def _create_product(self):
        if self._owner == 'Toyota':
            return ToyotaCar(self._owner)
        else:
            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)

Productの定義を行います。


# Product
class IProduct(ABC):

    def __init__(self, owner):
        self._owner = owner

    @abstractmethod
    def use(self):
        pass

    @abstractproperty
    def owner(self):
        pass

Productを使って、具体的なConcreteProductを定義します。


# Concrete Product
class Car(IProduct):

    def use(self):
        print(f'{self.owner}: I drive a car.')

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


class ToyotaCar(IProduct):

    def use(self):
        print(f'{self.owner}: I drive a car.')

    def use_hybrid_car(self):
        print(f'{self.owner}: I drive a priuse. It is the hybrid car.')

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


class Ship(IProduct):

    def use(self):
        print(f'{self.owner}: I drive a ship.')

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

作成したFactoryパターンのサンプルコードを使ってみます。


if __name__ == '__main__':
    car_factory = CarFactory()
    toyota_car = car_factory.create('Toyota')
    tesla_car = car_factory.create('Tesla')
    toyota_car.use()
    # tagawa
    toyota_car.use_hybrid_car()
    tesla_car.use()

    print(car_factory.registered_owners)

    ship_factory = ShipFactory()
    john_ship = ship_factory.create('John')
    mike_ship = ship_factory.create('Mike')
    john_ship.use()
    mike_ship.use()

    print(ship_factory.registered_owners)