설계패턴 20. Template Method Pattern

LSDrug·2024년 6월 12일

설계패턴(完)

목록 보기
20/26

1. 들어가기 전에...

템플릿이란, 사전적 의미로는 형판이라고 한다. 문자, 도형으로 구멍이 뚤려 있는 얇은 플라스틱 판을 생각해볼 수 있다.

실제로 어떤 도형이 그려질지는 필기구에 의해 결정되는데, 펜으로 그리면 펜으로 그린 도형이 되고, 연필로 그리면 연필로 그린 도형이 된다.

2. 정의

Template Method 패턴은 탬플릿 기능을 가진 패턴이다.

상위클래스에 템플릿 메서드가 정의되어 있고, 그 메서드 정의 안에는 추상 메서드가 사용되고 있다.

따라서 상위 클래스의 프로그램만 보면 추상 메서드를 어떻게 호출하고 있는지 알 수 있다.

추상 메서드를 실제로 구현하는 것은 하위 클래스, 하위 클래스 측에서 메서드를 구현하면 구체적인 처리가 결정된다.

그러나, 하위 클래스들에서 어떤 구현을 하더라도 처리의 큰 흐름은 상위클래스에서 결정한대로 이루어진다.

-> 상위 클래스에서 뼈대를 결정하며, 하위 클래스에서는 그 구체적인 내용을 결정하는 패턴

  • Base class에는 Template method 존재

  • Client는 Template method만 호출

  • Template method 내부에서 여러 step 함수 호출

  • Step 함수들은 Base class에서 제공되는 abstract method
    Child

  • Base class에서 상속받은 Child class는 abstract method인 step 함수들을 override 할 수 있는 권한이 생김

  • Child class는 step2()를 override 했으므로 Child object의 Template Method는 Base class의 step1() -> Child class의 step2() -> Base class의 step3() 순으로 호출

3. 개념 확장

로직 공통화

  • 로직을 공통화 할 수 있다.

  • 상위 클래스의 템플릿 메서드에서 알고리즘이 기술되어 있으므로, 하위 클래스측에서는 알고리즘을 일일이 기술할 필요가 없다.

상위 클래스와 하위 클래스의 연계

  • 템플릿 메서드 패턴에서는 상위 클래스와 하위 클래스가 긴밀하게 연계되어 작동하고 있다.

  • 따라서 상위 클래스에서 선언된 추상 메서드를 실제로 하위 클래스에서 구현할 때에는 그 메서드가 어느 타이밍에 호출되는지 이해해야 한다.

  • 상위 클래스의 소스 프로그램의 기술을 거의 하지 않으면 하위 클래스의 구현이 어려울 수 있다.

  • 반대로, 상위 클래스에서 기술을 많이 하게 되면 하위 클래스에서 자유도가 줄어든다.

  • 처리의 골격을 상위클래스에서 하고, 구체적인 것은 하위 클래스에서 수행하는데, 어떤 레벨에서 처리를 분배할지, 어떤 처리를 상위클래스에 두고, 하위클래스에 둘지 이런 것들은 정해진 매뉴얼이 없다.
    => 이것은 프로그램을 설계하는 사람의 몫이다.

하위 클래스를 상위 클래스와 동일시한다.

  • CharDisplay, StringDisplay의 인스턴스들은 AbstractDisplay를 부모로 두고 있다.

  • 하위 클래스의 타입이 특정되지 않아도 프로그램이 잘 작동하도록 만드는 것이 좋다.

-> 상위 클래스타입의 변수에 하위 클래스의 어떠한 타입의 인스턴스를 대입해도 제대로 동작해야 한다는 원칙은 리스코프 치환 원칙을 따라야 한다는 것이다.

4. 예시

Template Method 패턴을 사용해서 '문자나 문자열을 5회 반복해서 표시'하는 프로그램을 작성해보자.

class AbstractDisplay:
    def open(self):
        pass

    def textPrint(self):
        pass

    def close(self):
        pass

    def display(self):
        self.open()
        for i in range(5):
            self.textPrint()
        self.close()


class CharDisplay(AbstractDisplay):
    def __init__(self, ch):
        self.ch = ch

    def open(self):
        print("<<", end="")

    def textPrint(self):
        print(self.ch, end="")

    def close(self):
        print(">>")


class StringDisplay(AbstractDisplay):
    def __init__(self, string):
        self.string = string
        self.width = len(string)

    def open(self):
        self.printLine()

    def textPrint(self):
        print("|" + self.string + "|")

    def close(self):
        self.printLine()

    def printLine(self):
        print("+", end="")
        for i in range(self.width):
            print("-", end="")
        print("+")

# 결과
cd = CharDisplay("H")
sd1 = StringDisplay("hello, world")
sd2 = StringDisplay("Welcome to Korea")

cd.display()
sd1.display()
sd2.display()

profile
마약같은 코딩, 마약같은 코딩러

0개의 댓글