디자인패턴

[헤드퍼스트 디자인패턴] 템플릿메서드 패턴

hongyb 2024. 8. 20. 00:41

템플릿메서드 패턴을 알아보자. 

 

템플릿 메서드 패턴

템플릿 메서드 패턴

알고리즘의 골격을 정의한다. 템플릿 메서드를 사용하면 알고리즘의 일부 단계를 서브클래스에서 구현할 수 있으며, 알고리즘의 구조는 그대로 유지하면서 알고리즘의 특정단계를 서브클래스에서 재정의할 수 있다.    

 

템플릿 매서드 패턴

템플릿 메서드 패턴(Template Method Pattern)은 소프트웨어 디자인 패턴 중 하나로, 객체지향 프로그래밍에서 코드의 재사용성을 높이고, 일관성 있는 알고리즘 구현을 위해 고안되었다. 이 패턴의 핵심 아이디어는 알고리즘의 골격(뼈대)을 정의하고, 세부적인 처리는 서브클래스에서 담당하도록 하는 것이다. 

 

템플릿 메서드 패턴을 통해 코드 중복제거하고, 알고리즘 일관성 유지할 수 있으며, 변화하는 부분과 변화하지 않는 부분을 분리하여 유연한 설계를 할 수 있다. 

 

클래스 다이어그램은 다음과 같다. 

템플릿 메서드는 알고리즘의 각 단계를 정의하며, 서브클래스에서 일부 단계를 구현할 수 있도록 유도한다. 위에 다이어그램을 보면 templateMethod()는 primitiveOperation을 활용한다. 알고리즘은 이 단계들의 구체적인 구현으로부터 분리되어 있다. 

 

템플릿 메서드 패턴 코드 구현

클래스다이어그램을 참고하여 코드로 구현해보겠다.

 

AbstractClass이다. 추상 클래스이기 때문에 sub class에서 상속 후 오버라이드를 해야 한다.

public abstract class AbstractClass {
    public void templateMethod() {
        primitiveOperation1();

        if(selectCondition()) {
            primitiveOperation2();
        }
    }

    public abstract void primitiveOperation1();
    public abstract void primitiveOperation2();
    public boolean selectCondition() {
        return true;
    }
}

AbstractClass에 있는 selectCondition() 메서드는 항상 true를 return 한다. 이처럼 기본적인 내용만 구현되어 있거나, 아무 코드도 들어있지 않은 메서드를 후크(hook)라고 부른다. 후크를 자식 클래스에서 오버로드 하지 안흥면 기본으로 제공한 코드가 실행되기 때문에 그냥 무시해도 된다. 필요에 따라 자식 클래스에서 오버라이드해 사용할 수 있다.

 

 

다음은 ConcreteClass이다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class ConcreteClass extends AbstractClass {
    @Override
    public void primitiveOperation1() {
        System.out.println("primitive operation 1");
    }

    @Override
    public void primitiveOperation2() {
        System.out.println("primitive operation 2");
    }

    @Override
    public boolean selectCondition() {
        System.out.println("input condition(y/n) ");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String answer = null;

        try {
            answer = br.readLine();
        } catch (IOException ioe) {
            System.out.println("io exception");
        }

        if(answer.equals("y")) {
            return true;
        }
        return false;
    }
}

primiveOperation과 selectCondition를 오버라이드해서 구현했다. primitiveOperation은 필수로 오버라이드 해야 하며 selectCondition은 오버라이드 필수가 아니다.

 

할리우드 원칙(Hollywood Principle)

템플릿 메서드 패턴에서 사용하는 객체지향 원칙은 할리우드 원칙(Hollywood Principle)이다. 할리우드 원칙은 저수준 구성 요소들이 고수준 구성 요소에게 직접적으로 연락하거나 호출하지 않고, 고수준 구성 요소가 필요한 시점에 저수준 구성 요소를 호출하도록 하는 것이다. 즉, 저수준 구성 요소는 스스로 주도적으로 동작하지 않고, 고수준 구성 요소가 필요할 때 이를 호출하여 사용하게 된다.

 

할리우드 원칙을 통해 의존성 부패(dependency rot)를 방지할 수 있다. 고수준 구성 요소가 저수준 구성 요소에 의존하고, 저수준 구성 요소는 다시 고수준 구성 요소에 의존하는 식으로 의존성이 복잡하게 꼬여있는 상황을 의존성이 부패했다고 부른다. 할리우드 원칙을 사용하면, 저수준 구성 요소가 시스템에 접속할 수는 있지만 언제, 어떻게 그 구성 요소를 사용할지는 고수준 구성 요소가 결정한다.

 

템플릿 메서드 패턴에서는 AbstractClass에 있는 templateMethod()는 고수중 구성 요소이다. templateMethod()는 알고리즘을 장악하고 있고, 구현이 필요한 상황에만 서브클래스를 불러낸다. 이에 따라 AbstractClass의 클라이언트는 ConcreteClass와 같은 구상 클래스가 아닌 AbstractClass에 추상화되어 있는 부분에 의존한다.(AbstractClass에 있는 primitiveOperation 추상 메서드)