オブジェクトの生成方法を柔軟にし、生成ロジックと利用ロジックを分離するパターン群。
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!
Builder¶
多数のパラメータを持つ複雑なオブジェクトを、生成過程を分けて段階的に組み立てるパターン。コンストラクタ引数が増えすぎる「テレスコーピング・コンストラクタ」問題を避けられる。
class Pizza:
def __init__(self):
self.toppings = []
self.size = "M"
class PizzaBuilder:
def __init__(self):
self.pizza = Pizza()
def set_size(self, size):
self.pizza.size = size
return self
def add_topping(self, topping):
self.pizza.toppings.append(topping)
return self
def build(self):
return self.pizza
pizza = PizzaBuilder().set_size("L").add_topping("cheese").add_topping("olive").build()Prototype¶
既存のインスタンスを複製(clone)することで新しいオブジェクトを作るパターン。生成コストが高いオブジェクトや、
初期状態を維持したままバリエーションを作りたい場合に使う。Pythonでは標準ライブラリの copy.deepcopy がそのまま使える。
import copy
class Sheep:
def __init__(self, name):
self.name = name
original = Sheep("Dolly")
clone = copy.deepcopy(original)
clone.name = "Dolly Jr."
original.name'Dolly'