[python] 연산체인 패턴

연산체인 패턴은 객체 지향 프로그래밍에서 사용되는 디자인 패턴 중 하나입니다. 이 패턴은 여러 개의 객체를 연결하여 순서대로 처리할 수 있는 구조를 생성하는 것을 목적으로 합니다. 이러한 패턴은 객체 간의 결합도를 낮추고 유연한 처리 흐름을 구현할 수 있도록 도와줍니다.

동작 방식

연산체인 패턴은 여러 개의 연산자 객체로 구성됩니다. 각 객체는 한 가지 특정 연산을 처리하는데 책임을 지고 있습니다. 객체들은 연결된 목록 형태로 구성되어 있으며, 첫 번째 객체부터 마지막 객체까지 순서대로 처리하게 됩니다.

예시 코드

다음은 연산체인 패턴을 사용하여 문자열을 처리하는 예시 코드입니다.

class StringHandler:
    def __init__(self, successor=None):
        self.successor = successor
    
    def handle(self, string):
        # 현재 객체에서 처리 가능한 연산일 경우 처리
        if self.can_handle(string):
            self.process(string)
        # 처리할 수 없는 연산일 경우 다음 객체로 이동
        elif self.successor is not None:
            self.successor.handle(string)
        # 마지막 객체까지 처리되지 않은 경우 예외 처리
        else:
            raise ValueError("No handler available for the given string.")
    
    def can_handle(self, string):
        # 현재 객체에서 처리 가능한 연산인지 체크
        raise NotImplementedError("Subclasses must override this method.")
    
    def process(self, string):
        # 현재 객체에서 연산 처리
        raise NotImplementedError("Subclasses must override this method.")


class StringUppercaseHandler(StringHandler):
    def can_handle(self, string):
        # 모든 문자가 대문자일 경우 처리 가능
        return string.isupper()
    
    def process(self, string):
        print(string.upper())


class StringLowercaseHandler(StringHandler):
    def can_handle(self, string):
        # 모든 문자가 소문자일 경우 처리 가능
        return string.islower()
    
    def process(self, string):
        print(string.lower())


class StringLengthHandler(StringHandler):
    def can_handle(self, string):
        # 문자열의 길이가 5 이하일 경우 처리 가능
        return len(string) <= 5
    
    def process(self, string):
        print(f"Length: {len(string)}")


# 연산체인 생성
handler1 = StringUppercaseHandler()
handler2 = StringLowercaseHandler(handler1)
handler3 = StringLengthHandler(handler2)

# 문자열 처리
handler3.handle("HELLO")
handler3.handle("world")
handler3.handle("hi")

결론

연산체인 패턴은 객체 간의 결합도를 낮추고 유연한 처리 흐름을 구현하는데 유용한 디자인 패턴입니다. 여러 개의 객체를 연결하여 처리하는 구조를 만들어 원하는 기능을 순서대로 실행할 수 있습니다. 이를 통해 코드의 가독성과 유지보수성을 높일 수 있습니다.

참고 자료