KnowHow

技術的なメモを中心にまとめます。
検索にて調べることができます。

(オススメ2) Python基礎 オブジェクト指向5(Factory Method) 生成に関するデザインパターン

登録日 :2025/09/25 04:50
カテゴリ :Python基礎

Factory Methodとは

親クラスでインスタンスの生成方法を定め、具体的に何をどうやって作るかは子クラスで定めるようなパターン

生成したいオブジェクトのコンストラクタを呼び出してインスタンスを生成するのではなく、親クラスに定義された生成用のメソッドを呼び出してインスタンスの生成を行う

Template Methodを応用したパターン

生成に関するデザインパターン

Factory Methodの構成要素

Creator

  • Productを生成する抽象クラス
  • Productの生成を行うcreateメソッド
  • 具体的な生成方法を実装するためのAPIを提供

ConcreteCreator

  • Creatorを継承したクラス
  • 製品生成のための具体的な方法を実装
  • ConcreteProductクラスのインスタンスを返却

Product

  • Creatorのオブジェクト生成メソッドで生成される抽象クラス or インターフェース
  • 生成される製品が持つべきAPIを定義する

ConcreteProduct

  • Productを継承(実装)したクラス
  • ProductのAPIに沿った具体的な製品の機能を実装

Factory Methodのオブジェクト指向的要素

継承を利用したパターン

  • ProductとConcreteProduct, CreatorとConcreteCreatorの間にそれぞれ継承関係がある

  • Template Methodと同様に、処理(生成)の枠組みを親クラスで決定し、子クラスごとに具体的な生成方法を実装する

メリット・デメリット

メリット

  • オープンクローズドの原則に違反することなく新しいProductを追加することができる

  • オブジェクトの利用側とオブジェクトの結びつきを弱くする

デメリット

  • 簡単な生成処理の場合はFactory Methodを使用しない方がコードがシンプルになる

Factory Methodの使い所

  • 類似した複数種類のオブジェクトを生成する必要がある場合
    オープンクローズドの原則に違反することなく、別のオブジェクトの追加が可能

  • オブジェクトの生成ロジックが複雑な場合
    createメソッドを呼び出すだけで複雑な生成ロジックを記述せずに生成可能

  • Productの種類や生成手順が頻繁に変更される可能性がある場合
    利用側とProductの結びつきが弱いので、変更に強い設計となる

サンプルコード

クレジットカードを生成する例

from abc import ABCMeta, abstractmethod
from typing import List


class CreditCard(metaclass=ABCMeta):
    """Product Factory"""
    def __init__(self, _owner: str):
        self.__owner = _owner

    @property
    def owner(self) -> str:
        return self.__owner

    @abstractmethod
    def get_card_type(self) -> str:
        pass

    @abstractmethod
    def get_annual_charge(self) -> int:
        pass


class Platinum(CreditCard):
    def get_card_type(self) -> str:
        return "Platinum"

    def get_annual_charge(self) -> int:
        return 30000


class Gold(CreditCard):
    def get_card_type(self) -> str:
        return "Gold"

    def get_annual_charge(self) -> int:
        return 10000


class CreditCardFactory(metaclass=ABCMeta):
    """Create Factory"""
    @abstractmethod
    def create_credit_card(self, _owner: str) -> CreditCard:
        pass

    @abstractmethod
    def register_credit_card(self, credit_card: CreditCard):
        pass

    def create(self, _owner: str) -> CreditCard:
        credit_card = self.create_credit_card(_owner)
        self.register_credit_card(credit_card)
        return credit_card


credit_card_database: List[CreditCard] = []


class PlatinumCreditCardFactory(CreditCardFactory):
    def create_credit_card(self, _owner: str) -> CreditCard:
        return Platinum(_owner)

    def register_credit_card(self, credit_card: CreditCard):
        credit_card_database.append(credit_card)


class GoldCardFactory(CreditCardFactory):
    def create_credit_card(self, _owner: str) -> CreditCard:
        return Gold(_owner)

    def register_credit_card(self, credit_card: CreditCard):
        credit_card_database.append(credit_card)


if __name__ == '__main__':
    platinum_card_factory = PlatinumCreditCardFactory()
    platinum_card = platinum_card_factory.create("Tanaka")
    print(platinum_card.get_card_type())

    gold_credit_card_factory = GoldCardFactory()
    gold_card = gold_credit_card_factory.create('Suzuki')
    print(gold_card.get_card_type())

    print(credit_card_database)