Abstract Factory
Appendix-1 ソースコード全体
factory.py
- Factoryのインターフェイスを定義するモジュール
from abc import ABCMeta, abstractmethod
class Factory(metaclass=ABCMeta):
@abstractmethod
def createProgramA(self):
pass
@abstractmethod
def createProgramB(self):
pass
@abstractmethod
def createProgramC(self):
pass
program.py
- Factoryで生成するクラス群のインターフェイスを定義するモジュール
from abc import ABCMeta, abstractmethod
class ProgramA(metaclass=ABCMeta):
@abstractmethod
def exec(self):
pass
class ProgramB(metaclass=ABCMeta):
@abstractmethod
def exec(self):
pass
class ProgramC(metaclass=ABCMeta):
@abstractmethod
def exec(self):
pass
type01.py
- 特定の用途に特化したFactoryとクラス群の実装が配置されるモジュールその1
from factory import Factory
from program import ProgramA, ProgramB, ProgramC
class Type01Factory(Factory):
def createProgramA(self):
return Type01ProgramA()
def createProgramB(self):
return Type01ProgramB()
def createProgramC(self):
return Type01ProgramC()
class Type01ProgramA(ProgramA):
def exec(self):
return "Execute Type01ProgramA"
class Type01ProgramB(ProgramB):
def exec(self):
return "Execute Type01ProgramB"
class Type01ProgramC(ProgramC):
def exec(self):
return "Execute Type01ProgramC"
type02.py
- 特定の用途に特化したFactoryとクラス群の実装が配置されるモジュールその2
from factory import Factory
from program import ProgramA, ProgramB, ProgramC
class Type02Factory(Factory):
def createProgramA(self):
return Type02ProgramA()
def createProgramB(self):
return Type02ProgramB()
def createProgramC(self):
return Type02ProgramC()
class Type02ProgramA(ProgramA):
def exec(self):
return "Execute Type02ProgramA"
class Type02ProgramB(ProgramB):
def exec(self):
return "Execute Type02ProgramB"
class Type02ProgramC(ProgramC):
def exec(self):
return "Execute Type02ProgramC"
type03.py
- 特定の用途に特化したFactoryとクラス群の実装が配置されるモジュールその3
from factory import Factory
from program import ProgramA, ProgramB, ProgramC
class Type03Factory(Factory):
def createProgramA(self):
return Type03ProgramA()
def createProgramB(self):
return Type03ProgramB()
def createProgramC(self):
return Type03ProgramC()
class Type03ProgramA(ProgramA):
def exec(self):
return "Execute Type03ProgramA"
class Type03ProgramB(ProgramB):
def exec(self):
return "Execute Type03ProgramB"
class Type03ProgramC(ProgramC):
def exec(self):
return "Execute Type03ProgramC"
client.py
- FactoryとProgram*群を利用するクライアントクラス
class Client:
def __init__(self, factory):
self.factory = factory
def execProgramA(self):
p = self.factory.createProgramA()
print(p.exec())
def execProgramB(self):
p = self.factory.createProgramB()
print(p.exec())
def execProgramC(self):
p = self.factory.createProgramC()
print(p.exec())
if __name__=='__main__':
type1 = Client(Type01Factory())
type1.execProgramA() # => Execute Type01ProgramA
type1.execProgramB() # => Execute Type01ProgramB
type1.execProgramC() # => Execute Type01ProgramC
type2 = Client(Type02Factory())
type2.execProgramA() # => Execute Type02ProgramA
type2.execProgramB() # => Execute Type02ProgramB
type2.execProgramC() # => Execute Type02ProgramC
type3 = Client(Type03Factory())
type3.execProgramA() # => Execute Type03ProgramA
type3.execProgramB() # => Execute Type03ProgramB
type3.execProgramC() # => Execute Type03ProgramC
- ClientクラスはFactoryとProgram*群のインターフェイスにしか依存していない為、type04、type05、、、と実装群が増えてもClientクラスの変更は必要ない
- 処理の入り口となるClientクラスを変更せずに実装を丸ごと差し替える拡張ポイントとして利用することができる
- 例えば、DBの製品ごとに実行する製品依存のSQLを返すプログラムなどが想定できる
- Factory Methodの上位バージョンというよりはStrategyパターンの上位バージョンという捉え方をした方が実態に即しているように感じる
- 複数のクラスを渡すために使う
- 1種類のクラスしか返さないなら
Strategy
パターンを使えばよい
- 複数のクラスをまとめて渡したい&抽象化したい時に
Abstract Factory
を使う