🐥

Chain of Responsibility

2023/09/10に公開

Chain of Responsibility パターンは、複数のオブジェクトを一連の処理手段として連鎖させ、リクエストをこのチェーン上で逐次的に処理させるデザインパターンです。これにより、リクエストの送信者と受信者を分離し、処理を行うオブジェクトを動的に指定できます。

主要な構成要素:

  1. Handler (ハンドラ): 処理要求を持つインターフェースや抽象クラス。
  2. ConcreteHandler (具体的なハンドラ): Handler インターフェースを実装する具体的なクラス。次のハンドラへの参照を持つこともできます。

例:

ログの重要度に応じて、異なるログレベルでのメッセージ処理を考えてみましょう。

  1. Handler:

    from abc import ABC, abstractmethod
    
    class Logger(ABC):
        INFO = 1
        DEBUG = 2
        ERROR = 3
    
        def __init__(self, level):
            self.level = level
            self.next_logger = None
    
        def set_next(self, logger):
            self.next_logger = logger
    
        def log_message(self, level, message):
            if self.level <= level:
                self.write(message)
            if self.next_logger:
                self.next_logger.log_message(level, message)
    
        @abstractmethod
        def write(self, message):
            pass
    
    
  2. ConcreteHandler:

    class ConsoleLogger(Logger):
        def write(self, message):
            print(f"Standard Console::Logger: {message}")
    
    class ErrorLogger(Logger):
        def write(self, message):
            print(f"Error Console::Logger: {message}")
    
    class DebugLogger(Logger):
        def write(self, message):
            print(f"Debug Console::Logger: {message}")
    
    

使用方法:

    error_logger = ErrorLogger(Logger.ERROR)
    file_logger = DebugLogger(Logger.DEBUG)
    console_logger = ConsoleLogger(Logger.INFO)

    error_logger.set_next(file_logger)
    file_logger.set_next(console_logger)

    error_logger.log_message(Logger.INFO, "This is an information.")
    error_logger.log_message(Logger.DEBUG, "This is a debug message.")
    error_logger.log_message(Logger.ERROR, "This is an error message.")

利点:

  1. 分離: Chain of Responsibility パターンは、リクエストの送信者と受信者を分離します。これにより、リクエストの処理方法や処理の順番を動的に変更できます。
  2. 柔軟性: 複数の処理オブジェクトがリクエストを処理することが可能で、その順序や組み合わせを動的に変更できます。
  3. 拡張性: 新しい処理を追加する際に、既存のコードを変更することなく、新しいハンドラをチェーンに追加することができます。

Chain of Responsibility パターンは、複数のオブジェクトがリクエストを処理する能力を持っている場合や、リクエストを処理する具体的なオブジェクトを指定したくない場合に使用されます。

Discussion