記事の内容
複数エンドポイントを持つAPIを実装するのに、
どうまとめるのが良いか考えていてエンドポイント毎にクラスを作成して、
エンドポイント毎のクラスをまとめるクラスを作ると汎用性の高い
クラスができると思い作ってみました。
デザインパターンのFacadeっぽい感じになると思います。
Facacdeで調べると複数機能を1つにまとめるために使われることが多くて、
呼び出し先をまとめるためではなさそうなので、っぽいとつけました。
Facadeについてはこの記事がわかりやすかったです。
https://xtech.nikkei.com/it/article/COLUMN/20051216/226402/
設計
同じメソッドを持つクラスを作成するので抽象クラスを作成します。
抽象クラスの命名は末尾にBaseを付けるか先頭にAbstractを付けることが多いようです。
APIを使うのにトークン取得は何を共通で持たせたいので抽象クラスで実装して継承します。
クラスを作ったらFacadeクラスに分岐させて
クライアントから使いたい機能を指定して使っていきます。
コード
抽象クラス
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を引数に指定してください。