템플렛 메소드 패턴은 동일한 결과성을 위한 알고리즘을 수행하는 Framework 을 구성할 때 주로 사용되는 패턴으로, 해당 행위가 하위 클래스에서도 구조체를 가진채로 구현되도록 하기 위한 디자인 패턴이다. A single abstracti implementation of an algorithm 을 생성하기 위해 사용되며, 상속 대상 클래스들끼리 유사한 행위로 묶일 수 있을 때 사용된다. 다음과 같은 Coffee 를 만드는 Class 가 있다고 해보자.
class Coffee {
void prepareRecipe() {
boilWater();
brewCoffeeGrinds();
pourInCup();
addSugarAndMilk();
}
public void boilWater(){
// ...
}
// ...
}
이번에는 유사하게 Tea 를 만드는 Class 도 필요하다고 해보자.
class LemonTea {
void prepareRecipe() {
boilWater();
steepTeaBag();
pourInCup();
addLemon();
}
public void boilWater(){
// ...
}
// ...
}
두 클래스에서는 유사한 행위 및 구조적인 모습을 발견할 수 있다. boilWater 와 pourInCup() 함수는 중복된다고 볼 수 있으며, 종류는 다르지만 음료라는 결과를 위해 유사한 sequential 한 알고리즘이 수행된다는 것을 알 수 있다. 만약 다른 음료까지 추가한다고 하면, 똑같은 함수들을 지속적으로 생성해줘야 한다. 다음과 같은 형태로 변경해보자.
public abstract class CaffeineBeverage {
// 이 골격은 유지하고 싶고, 세부 Step 들은 override 가능하게 해준다
// 일부는 필수 impl 로 두고, 일부는 기본 구현을 제공하기도 한다
final void prepareRecipe(){ // 하위 함수들이 Override 할 수 없는 불변하는 함수
boilWater();
brew();
pourInCup();
addCondiments();
}
abstract void brew(); // brew, addCondiments 하는 방법은 각 하위 함수들마다 다름을 제공
abstract void addCondiments();
public void boilWater(){
// ...
}
public void pourInCup(){
// ...
}
}
위와 같이 설계된다면 Coffee extends CaffeineBeverage, Tea extends CaffeineBeverage 라는 하위 함수들을 만든 뒤에 brew() 와 addCondiments() 를 Override 하게 지정할 수 있다. 그리고 해당 클래스에서 prepareRecipe() 함수를 수행하면 원하는 결과를 수행할 수 있다.
위와 같이 해준다면 CaffeineBeverage 라는 상위의 단일 클래스가 특정 수행 알고리즘을 보호하고 제어할 권한을 가지게 된다. 또한 알고리즘 변화 필요시 해당 클래스만 변경되면 쉽게 유지 보수가 가능하고, 다른 음료들 또한 쉽게 추가될 수 있다는 장점을 가지고 있다.
Template Method 패턴에서 final 같이 알고리즘의 Skeleton 을 보호하는 함수를 Template Method (위 예시에서 prepareRecipe()) 라고 하며, 동일한 목적을 수행하는 알고리즘의 골격을 제안한다.
The template pattern defines the steps of an algorithm and allows the subclasses to implement one or more of the steps
참고로 Template Method Pattern 은 클래스들간의 관계인 inheritance 만을 가지고 정의를 할 수 있고, Object 관련된 내용은 등장하지 않는 것을 알 수 있다. 따라서 Template Method Pattern 은 Class Cope 의 패턴임을 알 수 있다.
Template Pattern 은 Strategy Pattern 과 유사하게 특정 알고리즘의 변형 및 variation 을 지원한다고 할 수 있지만, 그 방법이 다르다. Strategy 패턴에서는 알고리즘 전체를 바꾸어서 끼는, interface 단위 자체를 바꾸는 방식이였지만, Template 패턴은 알고리즘 뼈대는 유지하되, 일부 flow 를 바꾸는 상황에서 사용된다. 또한, Template Pattern 이 특수한 상황에 특화된 형태가 바로 Factory Pattern 이다.
참고) Hook Method
Template Method Pattern 과 관련 개념으로, 상황에 따라 기본값 / 혹은 아무 것도 제공하지 않은 상태로 abstract class 에 제공해주는 함수를 말한다. 하위 클래스들이 template 알고리즘에 "hook into" 해서 제어 가능하도록 설계된 부분을 제어할 수 있는 것이다 .
// ... CaffeineBeverage
final void prepareRecipe(){
// ...
if(customerWantsCondiments()) addCondiments();
}
// ...
boolean customerWantsCondiments(){
return true;
}
위와 같은 형식으로 addCondiments() 에 hook 함수인 customerWantsCondiments() 를 제공해서, 제공되는 상황에 따른 제어를 추가할 수 있다 (makeBeverage(false) 이런식으로 요청이 올게 할 수 있는 부분). JAVA API 에서도 많이 사용되는 것이 Hook 함수이다.
Hook 함수는 High Level Component 가 Low Level Component 에 개입의 여지를 줄 때만, 호출할 때만 호출될 수 있도록 하는 Hollywood Principle 디자인 원리에 대표적인 상황이다. 하위 클래스들은 는 자신이 원할 때 상위 클래스의 Template Method 의 흐름에 개입할 수 없기 때문이다.
출처
1) 에릭 프리먼, 『Head First Design Patterns』, O'Reilly Media (2004)
2) 중앙대학교 소프트웨어학부 이찬근 교수님 디자인 패턴 수업자료 중
'SW 설계 > Design Pattern' 카테고리의 다른 글
[Design Pattern] Creational - 빌더 패턴 (Builder Pattern) (0) | 2023.10.21 |
---|---|
[Design Pattern] Creational - 팩토리 메소드 패턴 (Factory Method Pattern) (0) | 2023.10.20 |
[Design Pattern] Behavioral - 중재자 패턴 (Mediator Pattern) (1) | 2023.10.20 |
[Design Pattern] Behavioral - 옵저버 패턴 (Observer Pattern) (0) | 2023.10.19 |
[Design Pattern] Behavioral - 전략 패턴 (Strategy Pattern) (0) | 2023.10.19 |