デザインパターンの一つであるFactoryパターンについて忘備録をまとめます。
Factory_Methodパターンとは
(概要)工場のように大量の製品を作成するときのデザインパターン
・製品側と工場側で分けて考えて、工場側でテンプレートを作成する。
・テンプレートに応じて、工場を作成して、各上場で製品を作成する。
(イメージ)
工場 → 船工場 → 船作成
→ 車工場 → 車作成
(目的)
・オブジェクトの生成とオブジェクトの具体的な処理を分離することで、
柔軟にオブジェクトを利用でき、再利用性を高める。(単一責任の原則を満たす)
(仕組み)
・インターフェース(抽象クラス)で処理の骨組みを作り(工場)、サブクラスを用いてオブジェクトを作成する
・サブクラスに応じて、作成されるオブジェクトのタイプを変える(船工場から船作成)
(構成要素)
・Product : 作成するオブジェクトの構成要素を定義するインターフェース(抽象クラス):工場の構成要素の原型
・ConcreteProduct : Productを具体化したクラス(複数作成):船工場、車工場、飛行機工場、、、
・Creator : Productを生成する処理を定義したインターフェース(抽象クラス):工場の処理の原型
・ConcreteCreator : Creatorを具体化したConcreteProductを作成するクラス:船、車、、、
(インターフェースの分離、依存性逆転の原則、などを満たしているものと考えられる)
Factory_Methodパターンのサンプルコード
FactroyパターンのPythonによるサンプルコードをメモします。
# factory_method.py
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
# ConcreteCreator
class CarFactory(IFactory):
# def _create_product(self):
# return Car(self._owner)
# tagawa. 果たしてこういう拡張の仕方で良いのだろうか。。。なんか違う気がする。
# IProduct(インターフェース)から、もっと拡張する必要があるのでは?
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
class IProduct(ABC):
def __init__(self, owner):
self._owner = owner
@abstractmethod
def use(self):
pass
@abstractproperty
def owner(self):
pass
# 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
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)