package template;
public class Coffee {
void prepareRecipe() {
boilWater();
brewCoffeeGrinds();
pourInCup();
addSugarAndMilk();
}
public void boilWater() {
System.out.println("Boiling Water");
}
public void brewCoffeeGrinds() {
System.out.println("Filtering");
}
public void pourInCup() {
System.out.println("Pouring");
}
public void addSugarAndMilk() {
System.out.println("Adding sugar and milk");
}
}
package template;
public class Tea {
void prepareRecipe() {
boilWater();
stepTeaBag();
pourInCup();
addLemon();
}
public void boilWater() {
System.out.println("Boiling Water");
}
public void stepTeaBag() {
System.out.println("TeaBagging");
}
public void pourInCup() {
System.out.println("Pouring");
}
public void addLemon() {
System.out.println("Adding lemon");
}
}
이러한 두 클래스가 있다고 하자. 이 때 자세히 보면 이들이 일정기능을 공유하고 있음을 알 수있다. 따라서 이를 추상클래스화 하여 통합할 수 있다.
package template;
public abstract class CaffeineBeverage {
final void prepareRecipe() {
boilWater();
brew();
pourInCup();
addCondiment();
}
abstract void brew();
abstract void addCondiment();
public void boilWater() {
System.out.println("Boiling Water");
}
public void pourInCup() {
System.out.println("Pouring");
}
}
package template;
public class Tea extends CaffeineBeverage{
public void brew() {
System.out.println("TeaBagging");
}
public void addCondiment() {
System.out.println("Adding lemon");
}
}
package template;
public class Coffee extends CaffeineBeverage{
public void brew() {
System.out.println("Filtering");
}
public void addCondiment() {
System.out.println("Adding sugar and milk");
}
}
이와 같은 패턴을
기본 템플릿 메서드 라고 한다
템플릿 메소드 패턴에서는 메소드에서 알고리즘의 골격을 정의한다. 알고리즘의 여러단계 중 일부는 서브클래스에서 구현할 수 있다. 이를 이용하면 알고리즘 구조는 유지하면서 특정 부분만 개편할 수 있다.
템플릿패턴은 실전에서 자주 사용되지만, 여기 나온 예시처럼 정확히 교과서적인 예시만 사용되는건 아니다.
후크는 추상클래스에서 선언되는 메소드지만, 기본적인 내용만 있고 아무 코드가 없는 메서드이다.
package template;
public abstract class CaffeineBeveragewHook {
final void prepareRecipe() {
boilWater();
brew();
pourInCup();
if (CustomerWantCondiment()) {
addCondiment();
}
}
abstract void brew();
abstract void addCondiment();
public void boilWater() {
System.out.println("Boiling Water");
}
public void pourInCup() {
System.out.println("Pouring");
}
boolean CustomerWantCondiment() {
return true;
}
}
이런식으로 CustomerWantCondiment라는 메서드를 만들고 이를 구현클래스에서 오버라이딩해서 조정이 가능하도록 하는것이다.
먼저연락하지말고 연락을 기다리라는 원칙이다.
고수준 구성요소가 저수준 구성요소에 의존하고 또 저수준이 고수준에 의존하고 이런 구조면 의존성 부패가 일어난다.
이를 방지하기 위해서 저수준은 고수준을 호출 할 수 없고, 고수준이 저수준을 호출 할 때 까지 대기해야한다.