LoginSignup
1
0

More than 1 year has passed since last update.

クラスをまとめるクラス設計(Facade?)

Posted at

記事の内容

複数エンドポイントを持つAPIを実装するのに、
どうまとめるのが良いか考えていてエンドポイント毎にクラスを作成して、
エンドポイント毎のクラスをまとめるクラスを作ると汎用性の高い
クラスができると思い作ってみました。

デザインパターンのFacadeっぽい感じになると思います。
Facacdeで調べると複数機能を1つにまとめるために使われることが多くて、
呼び出し先をまとめるためではなさそうなので、っぽいとつけました。

Facadeについてはこの記事がわかりやすかったです。
https://xtech.nikkei.com/it/article/COLUMN/20051216/226402/

設計

同じメソッドを持つクラスを作成するので抽象クラスを作成します。
抽象クラスの命名は末尾にBaseを付けるか先頭にAbstractを付けることが多いようです。

APIを使うのにトークン取得は何を共通で持たせたいので抽象クラスで実装して継承します。

クラス図.drawio.png

クラスを作ったらFacadeクラスに分岐させて
クライアントから使いたい機能を指定して使っていきます。

クラス図.drawio - コピー.png

コード

抽象クラス

from abc import ABC, abstractmethod

class AbstractClass(ABC):

    def __init__(self):
        # 必用に応じて
        pass

    def _get_token(self):
        """トークンの取得"""
        return token

    @abstractmethod
    def get_data(self):
        pass

エンドポイントごとにクラスを作成

抽象クラスを継承させてエンドポイント毎にClassA, ClassB, ClassCを作成するのをイメージしています。

class ClassA(AbstractClass):
    """●●取得用クラス"""

    def self(self):
        super().__init__()

    def get_token(self):
        super()._get_token()

    def get_data(self):
        return 'A Data'

class ClassB(AbstractClass):
    """●●取得用クラス"""

    def self(self):
        super().__init__()

    def get_token(self):
        super()._get_token()

    def get_data(self):
        return 'B Data'

class ClassC(AbstractClass):
    """●●取得用クラス"""

    def self(self):
        super().__init__()

    def get_token(self):
        super()._get_token()

    def get_data(self):
        return 'C Data'

Facadeクラス

今回はEnumも使ってみたかったのでインスタンス時にEnumで呼び出し先を
変える実装をしていみました。

Enumの命名規則の例があまり出てこなかったのですが、
Enumを付けているケースとTypeを付けるというケースがでてきました。

from enum import Enum

# Enumでクラスをまとめて持っておく
class EndpointEnum(Enum):
    A = ClassA
    B = ClassB
    C = ClassC


class ClassFacade():
    """●●クラスのFacade"""

    def __init__(self, target):
        
        # 引数がEnum出ない場合はエラーを表示
        if not isinstance(target, EndpointEnum):
            raise ValueError(f'{target}は指定できません。EndpointEnumのEnumを引数に指定してください。')

        # target.value()でインスタンス化する
        self._instance = target.value()

    def get_data(self):
        return self._instance.get_data()

クライアントからの呼び出し

FacadeクラスとEnumをimportして使用します。

from facade import ClassFacade, EndpointEnum

instance = ClassFacade(EndpointEnum.A)
print(instance.get_data())  # A Data

instance = ClassFacade(EndpointEnum.B)
print(instance.get_data())  # B Data

instance = ClassFacade(EndpointEnum.C)
print(instance.get_data())  # C Data

instance = ClassFacade('D')  # ValueError: Dは指定できません。EndpointEnumのEnumを引数に指定してください。
1
0
1

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
1
0