커피와 홍차 클래스를 구현해보면 다음과 같이 추가할 수 있다.
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 클래스에 코드가 중복되어 있고 거의 비슷하다. 두 클래스의 공통 알고리즘을 확인해보면 다음과 같다.
- 물을 끓인다.
- 뜨거운 물을 이용하여 커피 또는 홍차를 우려낸다.
- 만들어진 음료를 컵에 따른다.
- 각 음료에 맞는 첨가물을 추가한다.
이 알고리즘을 바탕으로 추상화 및 템플릿 메소드 패턴을 적용해보자.
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
에 해당한다.