2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonにおけるファクトリパターンの実装と応用:オブジェクト生成の戦略的分離

Posted at

概要

**ファクトリパターン(Factory Pattern)**は、
「オブジェクトの生成方法をカプセル化し、呼び出し側から分離する」ための設計手法である。

直接コンストラクタを呼ぶのではなく、生成をファクトリ経由にすることで、
柔軟性・再利用性・拡張性が高まり、OOP設計における依存関係の制御が容易になる。

本稿では、Pythonで実現するファクトリパターンの基礎から、
動的な型選択・DIとの併用・抽象化による戦略的な設計法まで解説する。


1. なぜファクトリが必要か?

❌ 呼び出し側が直接型を決めてしまう

if shape_type == "circle":
    shape = Circle()
elif shape_type == "square":
    shape = Square()

→ 呼び出し側にロジックと型の知識が集まり、密結合かつ変更耐性が低下


2. シンプルなファクトリ関数

def shape_factory(shape_type):
    if shape_type == "circle":
        return Circle()
    elif shape_type == "square":
        return Square()
    raise ValueError("Unknown shape")

→ 呼び出し側:

shape = shape_factory("circle")
shape.draw()

生成ロジックの隠蔽 + 呼び出し側の責務分離


3. クラスベースのファクトリ(インタフェース拡張可能)

class ShapeFactory:
    def create(self, shape_type):
        match shape_type:
            case "circle": return Circle()
            case "square": return Square()
            case _: raise ValueError("Invalid shape")

→ クラス化により設定依存の注入バインディング変更が容易になる


4. 登録型ファクトリ:拡張性の高い設計

class Factory:
    registry = {}

    @classmethod
    def register(cls, key, klass):
        cls.registry[key] = klass

    @classmethod
    def create(cls, key, *args, **kwargs):
        if key not in cls.registry:
            raise ValueError(f"{key} is not registered")
        return cls.registry[key](*args, **kwargs)
Factory.register("circle", Circle)
Factory.register("square", Square)

shape = Factory.create("circle")

Open/Closed Principle(拡張に開き、修正に閉じる) を満たす柔軟な構造


5. 実務におけるユースケース

✅ 設定ファイルによるサービス切替

if config["db"] == "sqlite":
    db = SqliteRepository()
elif config["db"] == "postgres":
    db = PostgresRepository()

→ ✅ ファクトリにロジックを集約し、アプリ本体は依存を意識しない構造に


✅ APIクライアントのバージョン切替

ApiClientFactory.create("v1")  # returns V1Client
ApiClientFactory.create("v2")  # returns V2Client

6. DIとの組み合わせによる抽象化の強化

class Controller:
    def __init__(self, factory: ShapeFactory):
        self.factory = factory

    def handle(self, shape_type):
        shape = self.factory.create(shape_type)
        shape.draw()

生成ロジックの注入とテスト分離が実現


7. よくある誤用と対策

❌ if文が増殖してswitch文のようになる

→ ✅ 辞書登録型や登録制ファクトリで分岐を排除する


❌ 型情報が呼び出し元に漏れている

→ ✅ 呼び出し元は「使う」ことに集中し、「作る」ことはファクトリへ委任する


結語

ファクトリパターンは、「生成」の責務を明確に切り出すことで、
構造の単純化と変更耐性の向上を同時に実現する設計戦略である。

  • オブジェクト生成を制御し、呼び出し元との結合を緩める
  • 動的選択・条件分岐・設定反映の処理を整理
  • DI・インタフェース分離との組み合わせでテスト容易性も強化

Pythonicとは、“オブジェクトの生成さえも意図として表現する” ことであり、
ファクトリパターンはその実装手段として最も普遍的かつ実用的な形で存在する。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?