KnowHow

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

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

登録日 :2025/10/01 20:45
カテゴリ :Python基礎

Abstract Factory

関連したオブジェクト(部品)のセットを生成するためのインターフェース(API)を提供するパターン

部品の具体的な実装には着目せず、抽象のAPIに注目して、そのAPIだけを使って、部品のセットを組み立てていく

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

構成要素

抽象的な要素群(Abstract)と具体的な要素群(Concrete)に分かれる

Abstract

Abstract Factory

  • インターフェースもしくは抽象クラス

  • 抽象的な部品であるAbstractProductを生成するためのAPIを定義する

AbstractProdut

  • インターフェイスもしくは抽象クラス

  • 部品ごとのAPIを定義する

Concrete

ConcreteFactory

  • AbstractFactoryを継承(実装)する子クラス

  • 具体的な部品であるConcreteProductを返すように実装を行う

ConcreteProduct

  • AbstractProductを継承(実装)する子クラス

  • ConcreteFactoryから返される具体的な部品

オブジェクト指向的要素

「ポリモーフィズム」を利用したパターン

「工場」「部品」ともに抽象と具体のセットになっていて、利用者は抽象のAPIのみを使用する

どのConcreteFactoryを使うかを切り替えるだけで、生成される部品群を切り替えることができる

メリット・デメリット

メリット

  • 具体的なクラスをクライアントから隠蔽する

  • 利用する部品群の整合性を保つことができる

デメリット

  • 必要なクラス数が多く、コードが必要以上に複雑になる可能性がある

使い所

関連する部品群を聞けられた種別ごとに整合性を保って切り替えたい場合

Factory Methodとの違い

生成するインスタンスの数

  • Factory Methodの場合、一つのインスタンスを生成
  • Abstract Factoryの場合、複数の部品のセットを生成

抽象化の対象

  • Factory Method: メソッド
  • Abstract Factory: クラス(インターフェース)

サンプルコード

例)OSのGUI

from abc import ABCMeta, abstractmethod


class Button(metaclass=ABCMeta):
    """ AbstractProduct"""
    @abstractmethod
    def press(self):
        pass


class CheckBox(metaclass=ABCMeta):
    """ AbstractProduct"""
    @abstractmethod
    def switch(self):
        pass


class GUIFactory(metaclass=ABCMeta):
    """AbstractFactory"""
    @abstractmethod
    def create_button(self) -> Button:
        pass

    @abstractmethod
    def create_checkbox(self) -> CheckBox:
        pass


class WindowsButton(Button):
    def press(self):
        print("Windows button was pressed.")


class WindowsCheckBox(CheckBox):
    def switch(self):
        print("Windows checkbox was switched.")


class WindowsGUIFactory(GUIFactory):
    def create_button(self) -> Button:
        return WindowsButton()

    def create_checkbox(self) -> CheckBox:
        return WindowsCheckBox()


class MacButton(Button):
    def press(self):
        print("Mac button was pressed.")


class MacCheckBox(CheckBox):
    def switch(self):
        print("Mac checkbox was switched.")


class MacGUIFactory(GUIFactory):
    def create_button(self) -> Button:
        return MacButton()

    def create_checkbox(self) -> CheckBox:
        return MacCheckBox()


def run(factory: GUIFactory):
    button = factory.create_button()
    checkbox = factory.create_checkbox()
    button.press()
    checkbox.switch()


if __name__ == '__main__':
    run(WindowsGUIFactory())
    run(MacGUIFactory())