Skip to main content

[Design Pattern] 행동 패턴 5. 템플릿 메서드 (Template Method)




템플릿 메서드 (Template Method) #

템플릿 메서드

  • 부모 클래스에서 알고리즘의 골격을 정의하고, 해당 알고리즘의 구조를 변경하지 않고 자식 클래스들이 알고리즘의 특정 단계들을 오버라이드​(재정의)​ 할 수 있도록 한다.



개념적인 예시 #

// 추상 클래스 
abstract class AbstractClass
{
    // 알고리즘의 뼈대를 정의한다. 
    public void TemplateMethod()
    {
        this.BaseOperation1();
        this.RequiredOperations1();
        this.BaseOperation2();
        this.Hook1();
        this.RequiredOperation2();
        this.BaseOperation3();
        this.Hook2();
    }

    // 이 동작들은 이미 구현되어 있다. 
    protected void BaseOperation1()
    {
        Console.WriteLine("AbstractClass says: I am doing the bulk of the work");
    }

    protected void BaseOperation2()
    {
        Console.WriteLine("AbstractClass says: But I let subclasses override some operations");
    }
    
    protected void BaseOperation3()
    {
        Console.WriteLine("AbstractClass says: But I am doing the bulk of the work anyway");
    }
    
    // 이 동작들은 자식 클래스에서 구현해야 한다. 
    protected abstract void RequiredOperations1();
    protected abstract void RequiredOperation2();
    
    // 훅(Hook)은 아무것도 하지 않는 구상 메소드를 부모 클래스에 정의하고, 
    // 자식 클래스에서 필요에 따라 재정의하여 사용하는 것이다. 
    protected virtual void Hook1() { }
    protected virtual void Hook2() { }
}

// 자식 클래스들은 추상 클래스의 추상 메서드들을 오버라이드해서 구현한다. 
class ConcreteClass1 : AbstractClass
{
    protected override void RequiredOperations1()
    {
        Console.WriteLine("1-1");
    }

    protected override void RequiredOperation2()
    {
        Console.WriteLine("1-2");
    }
}

class ConcreteClass2 : AbstractClass
{
    protected override void RequiredOperations1()
    {
        Console.WriteLine("2-1");
    }

    protected override void RequiredOperation2()
    {
        Console.WriteLine("2-2");
    }

    protected override void Hook1()
    {
        Console.WriteLine("2-Hook1");
    }
}

class Client
{
    // 클라이언트는 추상 클래스의 템플릿 메서드를 호출한다.
    public static void ClientCode(AbstractClass abstractClass)
    {
        // ...
        abstractClass.TemplateMethod();
        // ...
    }
}

class Program
{
    static void Main(string[] args)
    {
        Client.ClientCode(new ConcreteClass1()); // 1-1, 1-2
        
        Client.ClientCode(new ConcreteClass2()); // 2-1, 2-2, 2-Hook1
    }
}



References #