알고리즘의 골격을 정의하는 패턴으로, 알고리즘 구조를 변경하지 않고 알고리즘의 일부 내용을 서브 클래스에서 재정의할 수 있는 것이 장점이다.
AbstractClass
ConcreteClass
abstract class AbstractClass {
// 서브클래스에서 알고리즘을 바꾸지 못하게 하기 위해
// final로 선언하여 템플릿 메소드 고정
final void templateMethod() {
primitiveOperation1(); // 서브 클래스에서 구현할 추상 메서드 (위임할 수 있는 부분)
primitiveOperation2();
concreteOperation(); // 서브 클래스에서 오버라이딩 X
}
abstract void primitiveOperation1();
abstract void primitiveOperation2();
void concreteOperation() {
// concreteOperation() 메소드 코드
}
}
abstract class AbstractClass {
final void templateMethod() {
primitiveOperation1();
primitiveOperation2();
concreteOperation();
hook(); // 구현이 안된 빈 body
}
abstract void primitiveOperation1();
abstract void primitiveOperation2();
final void concreteOperation();
// concreteOperation() 메소드 코드
}
void hook() {} // 서브 클래스에 위임해서 알고리즘의 내용을 바꿀 수 있도록 함
}
hook()
스타버즈 커피 바리스타 매뉴얼
class Coffee {
void prepareRecipe() {
boilWater(); // 물 끓이는 중
brewCoffeeGrinds(); // 필터를 통해서 커피를 우려내는 중
pourInCup(); // 컵에 따르는 중
addSugarAndMilk(); // 설탕과 우유를 추가하는 중
}
...
}
class Tea {
void prepareRecipe() {
boilWater(); // 물 끓이는 중
steepTeaBag(); // 차를 우려내는 중
pourInCup(); // 컵에 따르는 중
addLemon(); // 레몬을 추가하는 중
}
...
}
서브 클래스에 있는 알고리즘을 한 군데로 모음
➜ 알고리즘 구현한 클래스CaffeinBeverage
void prepareRecipe() {
boilWater(); // 물 끓이는 중
brew(); // 커피 또는 홍차를 우려내는 중 (brewCoffeeGrinds(), steepTeaBag() 합침)
pourInCup(); // 컵에 따르는 중
addCondiments(); // 음료에 맞는 첨가물을 추가하는 중 (addSugarAndMilk(), addLemon() 합침)
}
⭐디자인 원칙: 먼저 연락하지 마세요. 저희가 연락 드리겠습니다.(헐리우드 원칙)
CaffeinBeverage
public abstract class CaffeinBeverage {
// 템플릿 메소드 (알고리즘 고정)
final void prepareRecipe() {
boilWater();
brew();
pourInCup();
addCondiments();
}
public void boilWater() {
System.out.println("물 끓이는 중");
}
public void pourInCup() {
System.out.println("컵에 따르는 중");
}
abstract void brew(); // 끓는 물에 무언가를 우려낸다
abstract void addCondiments(); // 무언가를 추가한다
}
Coffee
public class Coffee extends CaffeinBeverage {
@Override
public void brew() {
System.out.println("필터를 통해서 커피를 우려내는 중");
}
@Override
public void addCondiments() {
System.out.println("설탕과 우유를 추가하는 중");
}
}
Tea
public class Tea extends CaffeinBeverage {
@Override
public void brew() {
System.out.println("차를 우려내는 중");
}
@Override
public void addCondiments() {
System.out.println("레몬을 추가하는 중");
}
}
Main
public class BeverageTestDrive {
public static void main(String[] args) {
CoffeeWithHook coffeeHook = new CoffeeWithHook();
System.out.println("\n커피 준비중…");
coffeeHook.prepareRecipe();
}
}