Exist Technote

[Python] Template Method Pattern (템플릿 메소드) 본문

Design Pattern/Behavioral

[Python] Template Method Pattern (템플릿 메소드)

by_Exist 2020. 10. 18. 16:27

집을 만드는 과정. 결과물은 중간중간의 필요한 부품을 변경함으로써 달라질 수 있다. 출처 - https://refactoring.guru/design-patterns/template-method

Template Method Pattern이란?

  • 알고리즘의 뼈대만을 정의하고 각 단계에서 수행할 구체적 처리를 서브클래스로 미루는 패턴

활용

  • 어떤 알고리즘의 단계 중 변하지 않는 부분을 한 번 정의하여 변하는 부분을 서브클래스에서 정의할 수 있도록 남기고자 할 때 사용할 수 있다.
  • 서브클래스들의 인스턴스들이 공통적인 연산 알고리즘을 지닐 때 리팩토링을 목적으로 사용할 수 있다.

구조

# template_function에 필요한 getter들. (필수)
def get_text():
    return "plain-text"


def get_pdf():
    return "pdf"


def get_csv():
    return "csv"


# template_function에 필요한 converter. (훅)
def convert_to_text(data):
    print("[CONVERT]")
    return "{} as text".format(data)


# template_function에 필요한 saver. (훅)
def saver():
    print("[SAVE]")


# template_function 함수가 알고리즘의 전체적인 뼈대를 지니고 있다.
def template_function(getter, converter=False, to_save=False):
    data = getter()
    print("Got `{}`".format(data))

    if len(data) <= 3 and converter:
        data = converter(data)
    else:
        print("Skip conversion")

    if to_save:
        saver()

    print("`{}` was processed".format(data))


if __name__ == "__main__":
    template_function(get_text, to_save=True)
    template_function(get_pdf, converter=convert_to_text)
    template_function(get_csv, to_save=True)

# 서브클래싱 단계는 포함되어 있지 않지만
# 알고리즘의 뼈대와 알고리즘의 일부를 재정의하는 과정이 잘 드러나 있다.
from abc import ABC, abstractmethod

class AbstractClass(ABC):

    _hi = []

    # 알고리즘의 뼈대는 추상 클래스의 메소드로 설계되어 있다.
    def template_method(self):
        self.my_name_is()
        self.second_name()
        self.first_name()

    # 기본 - 서브클래스 전반에서 사용되는 연산
    def my_name_is(self):
        print("my name is ", end="")

    # 훅 - 서브클래스에서 필요에 따라 재정의하는 연산
    def first_name(self):
        pass

    # 필수 - 서브클래스에서 필수로 재정의해야 하는 연산
    @abstractmethod
    def second_name(self):
        pass


# 필수만 재정의
class Name(AbstractClass):

    def second_name(self):
        print("thon")


# 필수 및 훅 또한 정의
class FullName(AbstractClass):

    def first_name(self):
        print("Py", end="")

    def second_name(self):
        print("thon", end=" ")


if __name__ == "__main__":

    name = Name()
    name.template_method()

    full_name = FullName()
    full_name.template_method()

장단점

  • 장점
    • 클라이언트가 대규모 알고리즘의 특정 부분만 재정의하도록 하여 알고리즘의 다른 부분에서 발생하는 변경사항의 영향을 덜 받도록 할 수 있다.
    • 중복 코드를 수퍼 클래스로 가져올 수 있다.
  • 단점
    • 일부 클라이언트는 제공된 알고리즘 골격에 의해 제한될 수 있다.
    • 하위 클래스를 통해 기본 단계 구현을 억제하여 Liskov 대체 원칙을 위반할 수 있다.

여담

  • Factory Method, Abstract Factory와의 관계?
    • 템플릿 메서드 = 필요한 알고리즘을 서브클래스에서 구현
    • 팩토리 메서드 = 필요한 객체 생성을 서브클래스에서 구현
    • 추상 팩토리 = 필요한 객체군 또는 클래스군을 서브클래스에서 구현
  • 어떻게 동작하는지는 알겠지만, 어디에서 사용할 수 있을지는 여러 코드를 살펴보면서 익혀야 적절하게 활용할 수 있을 듯 하다.
Comments