デザインパターン#
分類 |
説明 |
代表例 🧩 |
|---|---|---|
生成に関するパターン |
オブジェクトの生成方法に関するパターン |
Singleton, Factory Method, Builder, Prototype |
構造に関するパターン |
オブジェクトやクラスの構造(組み立て方)に関するパターン |
Adapter, Decorator, Composite, Facade |
振る舞いに関するパターン |
オブジェクト間のやり取り・責務の分配方法に関するパターン |
Observer, Strategy, State, Command, Iterator |
Dependency Injection (依存性注入)#
依存関係を外部から注入するパターン
✅ メリット
テストしやすい:モック(模擬オブジェクト)を渡せる
柔軟性が高い:実装を変えても呼び出し側は影響を受けない
再利用性が高い:同じクラスを異なる依存関係で再利用可能
例
EngineとCarというオブジェクトがあるとする。
DIをしない場合は依存性を外部から変更できない状態。
class Engine:
def start(self):
print("Engine started")
# DIなし:CarがEngineを自分で作る(依存が固定されている)
class Car:
def __init__(self):
self.engine = Engine()
def run(self):
self.engine.start()
DIを行う場合、例えばconstructorにengineを渡したりする
# DIあり:Engineを外部から渡す(柔軟に差し替えられる)
class Car:
def __init__(self, engine: Engine):
self.engine = engine
def run(self):
self.engine.start()
# 実行
engine = Engine()
car = Car(engine) # Engineを注入
car.run()
DIの方法
(1) constructor injection
car = Car(engine)
(2) setter injection
car.set_engine(engine)
Singleton(シングルトン)#
インスタンスが1つしか存在しないようにする。インスタンスをグローバル変数のように扱う。
from datetime import datetime
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super(Singleton, cls).__new__(cls)
return cls._instance
class MyClass(Singleton):
def __init__(self, value):
self.value = value
m1 = MyClass("first")
print(f"{m1.value=}")
# m2を変えるとm1も変わる
m2 = MyClass("second")
print(f"{m1.value=}, {m2.value=}")
m1.value='first'
m1.value='second', m2.value='second'
Factory Method#
オブジェクトの生成処理をサブクラスに任せる(newを隠す)
class Animal:
def speak(self): pass
class Dog(Animal):
def speak(self): return "Woof!"
class Cat(Animal):
def speak(self): return "Meow!"
def animal_factory(kind: str) -> Animal:
if kind == "dog":
return Dog()
elif kind == "cat":
return Cat()
a = animal_factory("dog")
print(a.speak())
Woof!
Observer#
状態が変わったら通知(イベントリスナー)
class Subject:
def __init__(self):
self.observers = []
def attach(self, observer):
self.observers.append(observer)
def notify(self, msg):
for ob in self.observers:
ob.update(msg)
class Observer:
def update(self, msg):
print("Got:", msg)
s = Subject()
s.attach(Observer())
s.notify("Update available")
Got: Update available
Strategy#
アルゴリズムを切り替えられるようにする
class Strategy:
def execute(self, data):
pass
class Add(Strategy):
def execute(self, data):
return sum(data)
class Multiply(Strategy):
def execute(self, data):
result = 1
for x in data: result *= x
return result
def run(strategy: Strategy, data):
return strategy.execute(data)
print(run(Add(), [1, 2, 3]))
print(run(Multiply(), [1, 2, 3]))
6
6