CS

[Design Patterns] Template Method Pattern

ju_young 2024. 6. 19. 16:52
728x90

커피와 홍차 클래스를 구현해보면 다음과 같이 추가할 수 있다.

public class Coffee {
    void prepareRecipe() {
        boilWater();
        brewCoffeeGrinds();
        pourInCup();
        addSugarAndMilk();
    }

    public void boilWater() {
        System.out.println("물 끊이는 중");
    }

    public void brewCoffeeGrinds() {
        System.out.println("필터를 통해서 커피를 우려내는 중");
    }

    public void pourInCup() {
        System.out.println("컵에 따르는 중");
    }

    public void addSugarAndMilk() {
        System.out.println("설탕과 우유를 추가하는 중");
    }
}

public class Tea {
    void prepareRecipe() {
        boilWater();
        steepTeaBag();
        pourInCup();
        addLemon();
    }

    public void boilWater() {
        System.out.println("물 끊이는 중");
    }

    public void steepTeaBag() {
        System.out.println("차를 우려내는 중");
    }

    public void pourInCup() {
        System.out.println("컵에 따르는 중");
    }

    public void addLemon() {
        System.out.println("레몬을 추가하는 중");
    }
}

하지만 이 코드는 Coffee와 Tea 클래스에 코드가 중복되어 있고 거의 비슷하다. 두 클래스의 공통 알고리즘을 확인해보면 다음과 같다.

  1. 물을 끓인다.
  2. 뜨거운 물을 이용하여 커피 또는 홍차를 우려낸다.
  3. 만들어진 음료를 컵에 따른다.
  4. 각 음료에 맞는 첨가물을 추가한다.

이 알고리즘을 바탕으로 추상화 및 템플릿 메소드 패턴을 적용해보자.

Template Method Pattern 적용

public abstract class CaffeineBeverage {
    //template method
    final void prepareRecipe() {
        boilWater();
        brew();
        pourInCup();
        addCondiments();
    }

    abstract void brew();
    abstract void addCondiments();

    void boilWater() {
        System.out.println("물 끓이는 중");
    }

    void pourInCup() {
        System.out.println("컵에 따르는 중");
    }
}

public class Tea extends CaffeineBeverage {
    public void brew() {
        System.out.println("차를 우려내는 중");
    }

    public void addCondiments() {
        System.out.println("레몬을 추가하는 중");
    }
}

public class Coffee extends CaffeineBeverage {
    public void brew() {
        System.out.println("필터로 커피를 우려내는 중");
    }

    public void addCondiments() {
        System.out.println("설탕과 커피를 추가하는 중");
    }
}

NOTE

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

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

헐리우드 원칙

헐리우드 원칙을 활용하면 "의존성 부패(dependency rot)"를 방지할 수 있다.

NOTE
의존성 부패(dependency rot)

어떤 고수준 구성요소가 저수준 구성요소에 의존하고, 그 저수준 구성요소는 다시 고수준 구성요소에 의존하고, 그 고수준 구성요소는 다시 또 다른 구성요소에 의존하는 것처럼 의존성이 복잡하게 꼬여있는 것을 의존성 부패라 부른다.

 

헐리우드 원칙을 사용하면, 저수준 구성요소에서 시스템에 접속할 수 있지만, 언제 어떤 식으로 그 구성요소들을 사용할지는 고수준 구성요소에서 결정한다.

 

여기서 고수준 구성요소는 위 예시에서 CaffeineBeverage에 해당하고 저수준 구성요소는 Coffee, Tea에 해당한다.

 

[reference]
Head First Design Patterns

728x90