Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

生成に関するパターン(Creational Patterns)

オブジェクトの生成方法を柔軟にし、生成ロジックと利用ロジックを分離するパターン群。

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'