템플릿 메서드 패턴(Template Method Pattern)

  • 템플릿 메서드 패턴은 공통된 기능을 하나로 묶는 간단한 패턴입니다.
  • 즉 중복된 기능과 코드를 공통으로 처리하는 패턴입니다.

템플릿 메서드 패턴 구조

  • 템플릿 메서드는 두 개의 클래스로 구분합니다.
  • 상위 클래스에서 공통된 처리와 로직을 작성합니다.
  • 상위 클래스를 상속하는 하위 클래스는 구성 요소를 재구성하는 작은 코드로 구성됩니다.

템플릿 메서드 패턴: 상위 클래스

  • 샌드위치를 만드는 예제를 생각해보겠습니다.
  • 샌드위치는 내용물이 다르지만 빵 + 내용물 + 빵으로 제작하는 과정은 동일합니다.
  • 동일한 로직은 상위 클래스에서 구현합니다.
  • 하지만 빵 종류, 내용물 종류는 어떤 샌드위치를 만드냐에 따라 달라집니다.
  • 서로 다른 로직은 가상 함수로 선언하여 하위 클래스에서 구체적으로 작성합니다.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Abstract
{
public:
    std::string make()
    {
        std::string process = bread() + " + " + jam() + " + " + bread();

        return process;
    }

protected:
    virtual std::string bread() = 0;
    virtual std::string jam() = 0;
};

템플릿 메서드 패턴: 하위 클래스

  • 하위 클래스는 상위 클래스에서 선언한 가상함수를 실질적으로 구현하는 클래스입니다.
  • 가상함수로 구성된 상위 클래스의 메서드를 하위 클래스에서 구현합니다.
  • 또는 하위 클래스를 다시 상속하여 메서드 오버라이딩을 통해 변경이 있는 부분만 따로 작성이 가능합니다.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Strawberry :
    public Abstract
{
protected:
    std::string bread() override
    {
        return "Plain Bread";
    }

    std::string jam() override
    {
        return "Strawberry";
    }
};

class Blueberry :
    public Abstract
{
protected:
    std::string bread() override
    {
        return "Plain Bread";
    }

    std::string jam() override
    {
        return "Blueberry";
    }
};

class StrawberryBagel :
    public Strawberry
{
protected:
    std::string bread() override
    {
        return "Bagel";
    }
};

템플릿 메서드 패턴: 실행 코드

  • 템플릿 메서드는 구현과 사용이 간단합니다.
  • 다만 템플릿 메서드 패턴은 클래스의 구조를 변경하지 않고, 처리 로직의 일부를 재정의하는 패턴입니다.
  • 따라서 공통된 로직이 무엇인지 살펴보고, 이를 추상화하는 방법이 핵심입니다.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
int main(const int argc, const char* argv[])
{
    std::shared_ptr<Abstract> strawberry = std::make_shared<Strawberry>();
    std::string process = strawberry->make();
    std::cout << "[Strawberry] " << process << std::endl;

    std::shared_ptr<Abstract> strawberryBagel = std::make_shared<StrawberryBagel>();
    process = strawberryBagel->make();
    std::cout << "[StrawberryBagel] " << process << std::endl;

    std::shared_ptr<Abstract> blueberry = std::make_shared<Blueberry>();
    process = blueberry->make();
    std::cout << "[Blueberry] " << process << std::endl;

    return 0;
}
  • 실행 결과
1
2
3
[Strawberry] Plain Bread + Strawberry + Plain Bread
[StrawberryBagel] Bagel + Strawberry + Bagel
[Blueberry] Plain Bread + Blueberry + Plain Bread