디자인 패턴 & OOP

[디자인 패턴] 템플릿 메서드 패턴(Template Method Pattern)

cloud-grace 2024. 6. 4. 14:40

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

템플릿 메서드 패턴은 디자인 패턴(Design Pattern)중 행위 패턴(Behavioral Pattern)이다.
 

행위 패턴 : 클래스나 객체들이 서로 상호작용하는 방법이나 어떤 알고리즘, 작업을 어떤 객체에 할당하는 것이 좋을지 정의하는 패턴이다. 즉, 객체나 클래스의 교류 방법에 대해 정의하는 것이다. 하나의 객체만으로 수행할 수 없는 작업을 여러 객체로 나누면서 결합도를 최소화하게 해준다. 행위 클래스 패턴은 상속을 통해 알고리즘, 제어 흐름을 기술하고, 행위 객체 해턴은 하나의 작업을 수행하기 위해 객체 집합이 어떻게 협력하는지를 기술한다.

 
GoF 디자인 패턴에 의하면 템플릿 메서드 패턴은 상위클래스는 알고리즘의 골격만을 작성하고 구체적인 처리는 서브클래스로 위임한다.
 

템플릿 메서드 패턴 : 상속을 통해 상위 클래스의 기능을 확장할 때 사용하는 가장 대표적인 방법이다. 변하지 않는 기능은 상위 클래스에 만들어두고 자주 변경되며 확장할 기능은 하위 클래스에서 만들도록 한다.

 
템플릿 메서드 패턴은 알고리즘의 뼈대를 맞추는 것이 목적이라 할 수 있다. 즉, 전체적인 템플릿을 통일하지만 상속받은 클래스는 Hook 메서드를 이용하여 확장할 수 있도록 유연성을 주는 디자인 패턴이다.
 

템플릿 메서드 패턴 구조

출처 : https://yaboong.github.io/

  • AbstractClass : templateMethod()를 정의하며, 하위 클래스에서 확장하는 Hook 메서드를 제공한다. templateMethod()는 일반 메서드, 훅 메서드 모두 이용한다.
  • SubClass : 훅 메서드를 상속받아 재정의한다.

 

템플릿 메서드 패턴 예제 코드

패턴 적용 전

  • 위 코드를 보면 라떼를 제조하는 데에는 얼음, 커피, 우유를 넣는 행위는 동일한 코드이다. 즉, LatteTemplate 라는 클래스를 정의하여 중복된 코드를 제거할 수 있다.
public class VanillaLatte {
    public void addIce() {
        System.out.println("얼음을 넣는다.");
    }

    public void addCoffee() {
        System.out.println("커피를 넣는다.");
    }

    public void addMilk() {
        System.out.println("우유를 넣는다.");
    }

    public void addVanillaSyrup() {
        System.out.println("바닐라 시럽을 넣는다.");
    }
}
public class CaramelLatte {
    public void addIce() {
        System.out.println("얼음을 넣는다.");
    }

    public void addCoffee() {
        System.out.println("커피를 넣는다.");
    }

    public void addMilk() {
        System.out.println("우유를 넣는다.");
    }

    public void addCaramelSyrup() {
        System.out.println("카라멜 시럽을 넣는다.");
    }
}

 
 

패턴 적용 후

  • LatteTemplate 클래스를 추상 클래스로 선언한다.
  • 추상화할 메소드 1개를 추상 메소드로 선언한다.
  • makeLatte()은 템플릿 메소드이고, addSyrup()는 훅 메소드라고 볼 수 있다.
  • VanillaLatte 클래스와 CaramelLatte 클래스는 Latte 클래스를 상속받아 추상 메서드를 재정의한다.
// 추상 클래스: 알고리즘의 기본 구조를 정의
public abstract class LatteTemplate {
    public void makeLatte() { // 템플릿 메서드
        addIce();
        addCoffee();
        addMilk();
        addSyrup();
    }

    private void addIce() {
        System.out.println("얼음을 넣는다.");
    }

    private void addCoffee() {
        System.out.println("커피를 넣는다.");
    }

    private void addMilk() {
        System.out.println("우유를 넣는다.");
    }

    // 추상 메서드: 하위 클래스에서 구체화
    protected abstract void addSyrup();
}
// 구체적인 구현 클래스 1
class VanillaLatte extends LatteTemplate {
    @Override
    protected void addSyrup() {
        System.out.println("바닐라 시럽을 넣는다.");
    }
}
// 구체적인 구현 클래스 2
class CaramelLatte extends LatteTemplate {
    @Override
    protected void addSyrup() {
        System.out.println("카라멜 시럽을 넣는다.");
    }
}
// 실행 클래스
public class Main {
    public static void main(String[] args) {
        LatteTemplate vanillaLatte = new VanillaLatte();
        vanillaLatte.makeLatte();

        LatteTemplate caramelLatte = new CaramelLatte();
        caramelLatte.makeLatte();
    }
}

 

템플릿 메서드 패턴의 장점

  • 코드 재사용성 증가 : 공통된 알고리즘은 상위 클래스에서 정의되고, 세부 구현만 하위 클래스에서 정의하므로 중복 코드가 줄어든다.
  • 확장성 증가 : 새로운 라떼 종류를 추가할 때, 새로운 클래스만 작성하면 되므로 기존 코드를 수정할 필요가 없다.

 
 
 

참고 자료
https://steady-coding.tistory.com/384
https://4z7l.github.io/2020/12/25/design_pattern_GoF.html