Template Method Pattern
Template Method 디자인 패턴의 필요성과 그 구조에 대해 알아봅니다.읽는데 4분 정도 걸려요.필요성
아래와 같은 음료 제조법이 있다고 가정해보자.
Coffee Recipe
- Boil some water
- Brew coffee in Boiling water
- Pour beverage in cup
- Add sugar and milk
Tea Recipe
- Boil some water
- Steep tea in Boiling water
- Pour beverage in cup
- Add lemon
1, 3번 과정은 동일하다.
하지만 음료가 다르다고 같은 제조 과정을 중복해서 적으면 시간도 낭비되고, 수정할 때도 둘 다 수정해야 하는 불편함이 있다.
따라서 동일한 부분은 함수로 빼버리고, 다른 부분만 abstract로 처리하는 기법을 사용하면 이런 불편함을 줄일 수 있을 것이다.
Template Method Pattern
알고리즘의 뼈대를 정의하고, 서로 다른 부분은 subclass에 미루어 처리하는 디자인 패턴을 Template Method Pattern 이라고 한다.
위의 상황을 코드로 구현하며 알아보자.
public class Beverage {
final void prepareRecipe() {
boilWater();
brew();
pourInCup();
addCondiments();
}
abstract void brew();
abstract void addCondiments();
void boilWater() {
// boil water
}
void pourInCup() {
// pouring in cup
}
}
public class Coffee extends Beverage {
public void brew() {
// Brew coffee in Boiling water
}
public void addCondiments() {
// Add sugar and milk
}
}
public class Tea extends Beverage {
public void brew() {
// Steep tea in Boiling water
}
public void addCondiments() {
// Add lemon
}
}
이런식으로 하면 두 음료 모두 boilWater, pourInCup 과정은 동일한 코드를 사용할 수 있고,
음료에 따라 다른 brew, addCondiments 과정을 갖게 된다.
또한, 두 음료 모두 Beverage 클래스로 다형성을 유지할 수 있고, 음료 제작 과정은 둘 다 prepareRecipe를 호출하여 실행할 수 있다.
이 방식은 Hollywood 디자인 원칙 역시 준수하는데, 이게 뭐냐하면,
상위 컴포넌트(클래스)만 호출하고, 하위 컴포넌트는 호출하지 않고 등록만 하는 원칙이다.
위의 예시에선 Coffee, tea에서 기능을 수행하지 않고, brew, addCondiments만 등록을 했다.
실제 호출은 Beverage에서 prepareRecipe에서만 수행했다.
IRL
sort에서도 이와 비슷한 기능이 있다.
private static void mergeSort(Object src[], Object dest[],
int low, int high, int off) {
for (int i=low; i<high; i++) {
for (int j=i; j>low
&& ((Comparable)dest[j-i]).compareTo((Comparable)dest[j])>0; j--) {
swap(dest, j, j-1);
}
}
}
Comparable의 compareTo 메서드에서 객체의 비교하는 방법을 정의하게 되는데, 객체간 비교를 하고싶을 때 Comparable 인터페이스의 compareTo 메서드를 구현하면,
이에 따라 객체의 비교 방법이 달라져 mergeSort가 객체간 비교를 가능케 하는 것이다.