Python基礎 オブジェクト指向14(Composite) 構造に関するデザインパターン
| 登録日 | :2025/10/13 12:56 |
|---|---|
| カテゴリ | :Python基礎 |
Decorator
基本となるオブジェクトに対して、柔軟に機能追加をするパターン
-
継承よりも柔軟で、動的に機能追加が可能
(不要なサブクラスを追加しないなど) -
基本のオブジェクトを包むように見えるので、Wrapperパターンと呼ばれることもある。
構成要素
Component
- 抽象クラスまたはインターフェース
- 拡張される基本機能のAPIを定義
ConcreteComponent
- Componentを継承(実装)する子クラス
- 基本機能の具体的な実装を行う
Decorator
- Componentを継承(実装)し、基本機能の拡張(装飾)を行う抽象クラス
- 内部にComponentのAPIを保持
- ComponentのAPI定義の実装は子クラスに任せる
ConcreteDecorator
- Decoratorを継承する子クラス
- Componentの基本機能に具体的な拡張(装飾)を行う
オブジェクト指向的要素
- 「継承」「ポリモーフィズム」を利用したパターン
Component -> ConreteComponent
Component -> Decorator
Decorator -> ConcreteDecorator
- 機能を「追加される側」のComponentと、「追加する側」のDecoratorが同じAPIを持っており、利用者はどちらを操作しているかを意識する必要がない
メリット・デメリット
メリット
- 実行時の機能追加が容易にできる(継承しなくて良い)
- 複数の機能を組み合わせることが可能
デメリット
- 組み合わせた機能から特定の機能の削除は困難
- 振る舞いがデコレーターの組み合わせの順序に依存すr
使い所
- 追加したい機能のパターンが複数ある場合
- 追加したい機能のパターンに順序がある場合
- 継承を使ってオブジェクトの機能拡張が困難な場合
(Pythonには存在しないが、finalキーワードが付いたクラスなど)
サンプルコード
ログの出力を拡張する例
import datetime
from abc import ABCMeta, abstractmethod
class Component(metaclass=ABCMeta):
@abstractmethod
def get_log_message(self, _msg: str) -> str:
pass
class Logger(Component):
def get_log_message(self, _msg: str) -> str:
return _msg
class Decorator(Component):
def __init__(self, _component: Component):
self._component = _component
@abstractmethod
def get_log_message(self, _msg: str) -> str:
pass
class TimestampDecorator(Decorator):
def __init__(self, _component: Component):
super().__init__(_component)
def get_log_message(self, _msg: str) -> str:
now = datetime.datetime.now()
timestamp = now.strftime("%Y-%m-%d %H:%M:%S")
return self._component.get_log_message(f"{timestamp}: {_msg}")
class LogLevelDecorator(Decorator):
def __init__(self, _component: Component, _log_level: str):
super().__init__(_component)
self._log_level = _log_level
def get_log_message(self, _msg: str) -> str:
return self._component.get_log_message(f"[{self._log_level}]{_msg}")
if __name__ == "__main__":
message="Test Decorator pattern"
logger = Logger()
log_level_logger = LogLevelDecorator(logger, "INFO")
timestamp_logger = TimestampDecorator(log_level_logger)
print(logger.get_log_message(message))
print(log_level_logger.get_log_message(message))
print(timestamp_logger.get_log_message(message))