본문 바로가기

취업과 기본기 튼튼/빽 투더 기본기

[디자인 패턴 11편] 행동 패턴, 템플릿메쏘드(Template method)

1. 개념

템플릿메쏘드 패턴은 상위 클래스가 뼈대가 되는 로직을 구성하고,
하위 클래스들이 이 로직의 요소들을 각각 구현하는 패턴이다.

1.1. 구조

  • AbstractClass
    • ConcreteClass 가 상속받아야 할 추상 클래스
    • templateMethod() 에 클라이언트가 사용할 로직을 담는다.
    • 각 로직의 요소는 method1(), method2() 에 담기며, 이는 ConcreteClass 에서 구현한다.
  • ConcreteClass
    • AbstractClass 를 상속받아, 필요한 로직 요소 method() 를 필요에 맞게 구현한다.

1.2. 장점

  • 로직과 로직요소를 분리하여, 전체 로직은 동일하되 로직 요소를 각각 다르게할 수 있다.

1.3. 단점

  • 추상 클래스와 구현 클래스가 강하게 연결되어 있다.
    • 상속 때문에 하향적으로 강해지는 한편, 상위 클래스의 메쏘드를 사용하므로 상향적으로도 강해진다.
  • 로직 요소(추상 메쏘드) 가 많아지면 클래스 자체가 복잡해질 수 있다.

1.4. 활용 상황

  • 같은 로직을 가지고 있는 알고리즘들을 큰 뼈대 / 작은 요소로 나누어 관리하기가 쉬울 때.
  • 명확한 로직이 있고, 로직에 들어가는 변수들을 잘 컴포넌트화 시킬 수 있는 경우.

2. 구현

클라이언트는 다음과 같이 사용할 수 있다.

ConcreteClass1().template_method()
ConcreteClass2().template_method()

먼저 각 구체적인 클래스는 공통적으로 다음 추상 클래스를 상속받는다.
이 추상클래스는 template_method() 에 사용자가 사용할 인터페이스 로직을 담는다.

class AbstractClass(metaclass=ABCMeta):
  # 아래 메쏘드가 핵심입니다. 클라이언트는 이 메쏘드로 원하는걸 수행합니다.
  def template_method(self) -> None:
    self._required_operations1()
    self._required_operations2()

  # 아래 메쏘드들은 위 메쏘드의 로직 요소들입니다. 구체적인 클래스들이 정의합니다.
  @abstractmethod
  def _required_operations1(self) -> None:
    pass

  @abstractmethod
  def _required_operations2(self) -> None:
    pass

구체적인 클래스는 다음과 같이 정의된다.

class ConcreteClass1(AbstractClass):
  def _required_operations1(self) -> None:
    print("ConcreteClass1 says: Implemented Operation1")

  def _required_operations2(self) -> None:
    print("ConcreteClass1 says: Implemented Operation2")
class ConcreteClass2(AbstractClass):
  def _required_operations1(self) -> None:
    print("ConcreteClass2 says: Implemented Operation1")

  def _required_operations2(self) -> None:
    print("ConcreteClass2 says: Implemented Operation2")

3. 참고