[파이썬] 체인 오브 리스폰시빌리티 패턴과 처리 연쇄

체인 오브 리스폰시빌리티 패턴(Chain of Responsibility pattern)과 처리 연쇄(Processing Chain)는 소프트웨어 개발에서 유용하게 사용되는 디자인 패턴입니다. 이러한 패턴은 코드의 유연성과 확장성을 향상시키며, 다양한 요청을 처리하기 위한 간편한 방법을 제공합니다.

체인 오브 리스폰시빌리티 패턴

체인 오브 리스폰시빌리티 패턴은 요청이 발생했을 때 이를 처리할 수 있는 객체들의 체인을 만들어두는 패턴입니다. 각 객체는 해당 요청을 처리할 수 있는지 여부를 판단하고, 처리할 수 있다면 처리하고 그렇지 않다면 다음 객체에게 전달합니다. 이를 통해 요청에 대한 처리 로직을 분리하고, 유연하게 확장할 수 있게 됩니다.

예를 들어, 다음은 체인 오브 리스폰시빌리티 패턴을 사용하여 로깅을 처리하는 간단한 예제 코드입니다.

class Logger:
    def __init__(self, level):
        self.level = level
        self.next_logger = None

    def set_next_logger(self, next_logger):
        self.next_logger = next_logger

    def log_message(self, level, message):
        if self.level <= level:
            self.write_message(message)
        if self.next_logger is not None:
            self.next_logger.log_message(level, message)

    def write_message(self, message):
        raise NotImplementedError("This method should be implemented by subclasses")

class InfoLogger(Logger):
    def write_message(self, message):
        print(f"[INFO] {message}")

class ErrorLogger(Logger):
    def write_message(self, message):
        print(f"[ERROR] {message}")

class DebugLogger(Logger):
    def write_message(self, message):
        print(f"[DEBUG] {message}")

# 로거 인스턴스 생성
logger = InfoLogger(Logger.INFO)
error_logger = ErrorLogger(Logger.ERROR)
debug_logger = DebugLogger(Logger.DEBUG)

# 로깅 체인 구성
logger.set_next_logger(error_logger)
error_logger.set_next_logger(debug_logger)

# 로깅 메시지 전달
logger.log_message(Logger.DEBUG, "This is a debug message")

위 예제 코드에서는 Logger라는 추상 클래스를 정의하고, InfoLogger, ErrorLogger, DebugLogger 등의 구체적인 로깅 클래스들을 구현합니다. 각 로거 객체는 다음 로거를 참조하는 next_logger 속성을 가지며, 요청이 발생하면 해당 로거가 처리할 수 있다면 처리하고 그렇지 않다면 다음 로거로 전달합니다. 따라서 우리는 로깅 처리를 원하는 순서대로 로깅 체인을 구성하면 됩니다.

위 예제 코드를 실행하면, “This is a debug message”라는 메시지가 DebugLogger를 거쳐서 차례대로 로그로 출력됩니다. 이는 요청이 Logger.DEBUG 레벨에 맞기 때문에 해당 로그 이상의 레벨을 가진 로거에서 모두 처리되기 때문입니다.

처리 연쇄

처리 연쇄는 체인 오브 리스폰시빌리티 패턴과 비슷한 개념을 가지고 있습니다. 처리 연쇄는 여러 개의 객체가 연결되어 있는데, 각 객체들은 처리를 위임받은 후에 필요한 작업을 수행하고 다음 객체로 처리를 전달합니다.

예를 들어, 다음은 처리 연쇄를 사용하여 이벤트 처리를하는 간단한 코드입니다.

class EventHandler:
    def __init__(self):
        self.next_handler = None

    def set_next_handler(self, next_handler):
        self.next_handler = next_handler

    def handle_event(self, event):
        self.process_event(event)
        if self.next_handler is not None:
            self.next_handler.handle_event(event)

    def process_event(self, event):
        raise NotImplementedError("This method should be implemented by subclasses")

class ButtonClickHandler(EventHandler):
    def process_event(self, event):
        if event.type == "BUTTON_CLICK":
            print("Button Clicked!")

class MouseMoveHandler(EventHandler):
    def process_event(self, event):
        if event.type == "MOUSE_MOVE":
            print("Mouse Moved!")

class KeyPressHandler(EventHandler):
    def process_event(self, event):
        if event.type == "KEY_PRESS":
            print("Key Pressed!")

# 이벤트 핸들러 인스턴스 생성
button_click_handler = ButtonClickHandler()
mouse_move_handler = MouseMoveHandler()
key_press_handler = KeyPressHandler()

# 이벤트 처리 체인 구성
button_click_handler.set_next_handler(mouse_move_handler)
mouse_move_handler.set_next_handler(key_press_handler)

# 이벤트 처리
event = Event("BUTTON_CLICK")
button_click_handler.handle_event(event)

위 예제 코드에서는 EventHandler라는 추상 클래스를 정의하고, ButtonClickHandler, MouseMoveHandler, KeyPressHandler 등의 구체적인 이벤트 핸들러 클래스들을 구현합니다. 각 핸들러 객체는 next_handler 속성을 가지며, 받은 이벤트를 처리하거나 다음 핸들러로 전달합니다.

위 예제 코드를 실행하면, “Button Clicked!”라는 메시지가 출력됩니다. 이는 생성한 event 객체의 타입이 “BUTTON_CLICK”이기 때문에 첫 번째 핸들러인 ButtonClickHandler에서 처리되었기 때문입니다.

이러한 처리 연쇄 패턴은 이벤트 처리뿐만 아니라 오류 처리, 인증 및 권한 부여, 데이터 변환 등 다양한 상황에서 유용하게 사용될 수 있습니다.

체인 오브 리스폰시빌리티 패턴과 처리 연쇄는 소프트웨어 개발에서 유연하고 확장 가능한 코드를 작성하는 데 도움이 되는 디자인 패턴입니다. 이러한 패턴을 적절히 활용하면 코드의 가독성과 유지 보수성을 향상시킬 수 있습니다.