템플릿 메소드 패턴(Template Method Pattern)
템플릿 메소드 패턴(Template Method Pattern)은 알고리즘의 골격을 정의한다.
알고리즘의 일부 단계를 서브클래스에서 구현할 수 있다.
알고리즘의 구조는 유지하며 특정 단계만 서브클래스에서 재정의할 수 있다.
비슷한 형태의 클래스, 즉 중복되는 코드가 있는 클래스들의 공통된 부분을 추상화해서 또 다른 base 클래스로 만드는 것이다. 한 마디로 프로그램의 '틀'이라고 볼 수 있다.

스타버즈라는 카페의 커피와 티 레시피는 거의 흡사하다. 이 중 공통된 부분을 묶어서 하나의 베이스로 만든다.
void perpareRecipe() {
boilWater();
brew();
pourInCup();
addCondiments();
}
perpareRecipe()는 커피와 티의 세부적인 내용이 다르므로 추상 메소드로 선언하고, boilWater()와 pourInCup() 메소드는 공통된 부분이므로 슈퍼클래스로 사용한다.
커피, 차를 우려내는 brew() 메소드와 첨가물을 추가하는 addCondiments() 메소드도 서브 클래스에서 구현하도록 추상화 메소드로 선언해준다.
그리고 서브클래스 Coffee와 Tea는 prepareRecipe를 오버라이드 해서 구현하고, 각각의 개별적인 메소드를 구현한다.
Beverage를 만드는 과정이 모두 담겨 있고, 처리 순서를 정해놓은 perpareRecipe() 메소드가 템플릿 메소드이다.
public abstract class CaffeineBeverage {
// final로 선언하여 이를 상속 받는 클래스가 재정의하지 못하도록 한다
final void prepareRecipe() {
boilWater(); // 이 클래스 내에서 정의
brew(); // 서브 클래스에서 재정의
pourInCup(); // 이 클래스 내에서 정의
addCondiments(); // 서브 클래스에서 재정의
}
abstract void brew();
abstract void addCondiments();
void boilWater() {
System.out.println("Boiling water");
}
void pourInCup() {
System.out.println("Pouring into cup");
}
}
템플릿 메소드를 이용해서 CaffeineBeverage 클래스 내에서 처리할 수 있는 메소드는 처리하고, 서브 클래스에서 재정의 해야 하는 메소드는 추상 메소드로 선언한다.
템플릿 메소드를 final로 선언하여 이를 상속 받는 하위 클래스에서 재정의하여 사용할 수 없도록 한다.
testDrive에서 coffee.prepareRecipe()를 돌려보면 정의된 메소드들이 차례대로 돌아간다.
후크(hook)
추상 클래스에서 선언되는 아무것도 들어있지 않거나 기본적인 내용만 구현되어 있는 메소드
public abstract class CaffeineBeverageWithHook {
// Template Method
final void prepareRecipe() {
boilWater();
brew();
pourInCup();
if (customerWantsCondiments()) {
addCondiments();
}
// Hook Method
boolean customerWantsCondiments() {
return true;
}
...
}
책의 예제에서는 위와 같이 후크 메소드를 추가했다.
서브 클래스에서 이 메소드를 오버라이드 하여 재정의 해 사용할 수도 있고, 그냥 무시할 수도 있다. 무시하게 되면 추상 클래스에서 구현되어 있는 코드가 실행된다.
이 추상 클래스를 구현하는 한 서브 클래스에서 다음과 같이 오버라이드 할 수 있다.
public class CoffeeWithHook extends CaffeineBeverageWithHook {
...
public boolean customerWantsCondiments() {
String answer = getUserInput();
if (answer.toLowerCase().startsWith("y")) {
return true;
} else {
return false;
}
}
...
}
고객에게 첨가물을 넣을지 말지에 대한 의사를 입력 받아서 boolean 값을 return 해주는 메소드로 재정의했다.
hook를 이용하면 상황에 따라 알고리즘의 진행을 변경할 수 있다.
할리우드 원칙(Hollywood Principle)
먼저 연락하지 마세요. 저희가 연락 드리겠습니다.
할리우드 원칙을 활용하면 의존성 부패를 방지할 수 있다.
의존성 부패란?
고수준 요소가 저수준 요소에 의존하고, 그 저수준 요소는 다시 고소준 요소에 의존하고, 그 고수준 요소는 또 다른 저수준 요소에 의존하고... 같은 식 으로 의존성이 복잡하게 꼬여있는 상황
할리우드 원칙을 활용하면, 저수준 요소가 시스템에 접속할 수는 있지만, 언제 어떻게 사용할지는 고수준 요소가 결정한다.
즉, 저수준 구성 요소는 절대 고수준 구성 요소를 직접 호출할 수 없다는 얘기다.
'Design Pattern' 카테고리의 다른 글
[Headfirst Design Pattern] 복합 패턴(Compound Patterns) (0) | 2024.06.13 |
---|---|
[Headfirst Design Parttern] 어댑터 패턴&퍼사드 패턴(Adapter Pattern & Facade Pattern) (0) | 2024.06.05 |
[Headfirst Design Pattern] 데코레이터 패턴(Decorator Pattern) (2) | 2024.04.24 |
[Headfirst Design Pattern] 옵저버 패턴(Observer Pattern) (0) | 2024.04.12 |
템플릿 메소드 패턴(Template Method Pattern)
템플릿 메소드 패턴(Template Method Pattern)은 알고리즘의 골격을 정의한다.
알고리즘의 일부 단계를 서브클래스에서 구현할 수 있다.
알고리즘의 구조는 유지하며 특정 단계만 서브클래스에서 재정의할 수 있다.
비슷한 형태의 클래스, 즉 중복되는 코드가 있는 클래스들의 공통된 부분을 추상화해서 또 다른 base 클래스로 만드는 것이다. 한 마디로 프로그램의 '틀'이라고 볼 수 있다.

스타버즈라는 카페의 커피와 티 레시피는 거의 흡사하다. 이 중 공통된 부분을 묶어서 하나의 베이스로 만든다.
void perpareRecipe() {
boilWater();
brew();
pourInCup();
addCondiments();
}
perpareRecipe()는 커피와 티의 세부적인 내용이 다르므로 추상 메소드로 선언하고, boilWater()와 pourInCup() 메소드는 공통된 부분이므로 슈퍼클래스로 사용한다.
커피, 차를 우려내는 brew() 메소드와 첨가물을 추가하는 addCondiments() 메소드도 서브 클래스에서 구현하도록 추상화 메소드로 선언해준다.
그리고 서브클래스 Coffee와 Tea는 prepareRecipe를 오버라이드 해서 구현하고, 각각의 개별적인 메소드를 구현한다.
Beverage를 만드는 과정이 모두 담겨 있고, 처리 순서를 정해놓은 perpareRecipe() 메소드가 템플릿 메소드이다.
public abstract class CaffeineBeverage {
// final로 선언하여 이를 상속 받는 클래스가 재정의하지 못하도록 한다
final void prepareRecipe() {
boilWater(); // 이 클래스 내에서 정의
brew(); // 서브 클래스에서 재정의
pourInCup(); // 이 클래스 내에서 정의
addCondiments(); // 서브 클래스에서 재정의
}
abstract void brew();
abstract void addCondiments();
void boilWater() {
System.out.println("Boiling water");
}
void pourInCup() {
System.out.println("Pouring into cup");
}
}
템플릿 메소드를 이용해서 CaffeineBeverage 클래스 내에서 처리할 수 있는 메소드는 처리하고, 서브 클래스에서 재정의 해야 하는 메소드는 추상 메소드로 선언한다.
템플릿 메소드를 final로 선언하여 이를 상속 받는 하위 클래스에서 재정의하여 사용할 수 없도록 한다.
testDrive에서 coffee.prepareRecipe()를 돌려보면 정의된 메소드들이 차례대로 돌아간다.
후크(hook)
추상 클래스에서 선언되는 아무것도 들어있지 않거나 기본적인 내용만 구현되어 있는 메소드
public abstract class CaffeineBeverageWithHook {
// Template Method
final void prepareRecipe() {
boilWater();
brew();
pourInCup();
if (customerWantsCondiments()) {
addCondiments();
}
// Hook Method
boolean customerWantsCondiments() {
return true;
}
...
}
책의 예제에서는 위와 같이 후크 메소드를 추가했다.
서브 클래스에서 이 메소드를 오버라이드 하여 재정의 해 사용할 수도 있고, 그냥 무시할 수도 있다. 무시하게 되면 추상 클래스에서 구현되어 있는 코드가 실행된다.
이 추상 클래스를 구현하는 한 서브 클래스에서 다음과 같이 오버라이드 할 수 있다.
public class CoffeeWithHook extends CaffeineBeverageWithHook {
...
public boolean customerWantsCondiments() {
String answer = getUserInput();
if (answer.toLowerCase().startsWith("y")) {
return true;
} else {
return false;
}
}
...
}
고객에게 첨가물을 넣을지 말지에 대한 의사를 입력 받아서 boolean 값을 return 해주는 메소드로 재정의했다.
hook를 이용하면 상황에 따라 알고리즘의 진행을 변경할 수 있다.
할리우드 원칙(Hollywood Principle)
먼저 연락하지 마세요. 저희가 연락 드리겠습니다.
할리우드 원칙을 활용하면 의존성 부패를 방지할 수 있다.
의존성 부패란?
고수준 요소가 저수준 요소에 의존하고, 그 저수준 요소는 다시 고소준 요소에 의존하고, 그 고수준 요소는 또 다른 저수준 요소에 의존하고... 같은 식 으로 의존성이 복잡하게 꼬여있는 상황
할리우드 원칙을 활용하면, 저수준 요소가 시스템에 접속할 수는 있지만, 언제 어떻게 사용할지는 고수준 요소가 결정한다.
즉, 저수준 구성 요소는 절대 고수준 구성 요소를 직접 호출할 수 없다는 얘기다.
'Design Pattern' 카테고리의 다른 글
[Headfirst Design Pattern] 복합 패턴(Compound Patterns) (0) | 2024.06.13 |
---|---|
[Headfirst Design Parttern] 어댑터 패턴&퍼사드 패턴(Adapter Pattern & Facade Pattern) (0) | 2024.06.05 |
[Headfirst Design Pattern] 데코레이터 패턴(Decorator Pattern) (2) | 2024.04.24 |
[Headfirst Design Pattern] 옵저버 패턴(Observer Pattern) (0) | 2024.04.12 |