이번에는 템플릿 메소드 패턴(template method pattern)에 대해서 알아보도록 하겠습니다.
이전글들과 마찬가지로 Head First Design Pattern 책을 참고했습니다.
템플릿 메소드 패턴에서는 메소드에서 알고리즘의 골격을 정의합니다.
알고리즘의 여러 단계 중 일부는 서브클래스에서 구현할 수 있습니다.
템플릿 메소드를 이용하면 알고리즘의 구조는 그대로 유지하면서 서브클래스에서 특정단계를 재정의 할 수 있습니다.
즉, 템플릿 메소트 패턴은 알고리즘 틀을 만들기 위한 것입니다.
아래 예제 소스코드는 커피, 차를 만드는 과정을 프로그램 한 것입니다.
커피, 차를 만드는 일련의 과정을 메소드로 정의합니다.
그리고, 이 메소드 중 하나 이상이 추상메소드로 정의되며, 그 추상 메소드는 서브클래스에서 구현됩니다.
이렇게 하면 서브클래스에서 일부분을 구현할 수 있도록 하면서도 알고리즘의 구조는 바꾸지 않아도 됩니다.
public abstract class CaffeinBeverageWithHook {
final void prepareRecipe() {
// 기본적인 커피 or 차 만드는 프로세스
boilWater(); // 물을 끓이기
brew(); // 우려내기
pourInCup(); // 컵에 따르고
if(customerWantsCondiments() == true) {
addCodiments(); // 첨가할 것들 첨가하기
}
}
abstract public void brew();
abstract public void addCodiments();
public void boilWater() {
System.out.println("물을 끓이는 중");
}
public void pourInCup() {
System.out.println("컵에 따르는 중");
}
public boolean customerWantsCondiments() {
return true;
}
}
public class Coffee extends CaffeinBeverageWithHook {
@Override
public void brew() {
System.out.println("필터를 통해 커피를 우려내는 중");
}
@Override
public void addCodiments() {
System.out.println("설탕과 우유를 추가하는 중");
}
}
public class Tea extends CaffeinBeverageWithHook {
@Override
public void brew() {
System.out.println("차를 우려내는 중");
}
@Override
public void addCodiments() {
System.out.println("레몬을 추가하는 중");
}
}
후크(hook)
후크는 추상 클래스에서 선언되는 메소드 긴 하지만 기본적인 내용만 구현되어 있거나 아무 코드도 들어있지 않은 메소드 입니다.
이렇게 하면 서브클래스에서는 다양한 위치에서 알고리즘에 끼어들 수도 있고, 그냥 무시하고 넘어 갈 수도 있습니다.
final void prepareRecipe() {
// 기본적인 커피 or 차 만드는 프로세스
boilWater(); // 물을 끓이기
brew(); // 우려내기
pourInCup(); // 컵에 따르고
if(customerWantsCondiments() == true) {
addCodiments(); // 첨가할 것들 첨가하기
}
}
public boolean customerWantsCondiments() {
return true;
}
바로 위 customerWantsCondiments 메소드가 서브클래스에서 필요에 따라 오버라이드 할 수 있는 메소드 이므로 후크입니다.
디자인 원칙
할리우드 원칙(Hollywood Principle) : 먼저 연락하지 마세요. 저희가 연락드리겠습니다.
할리우드 원칙을 활용하면 의존성 부패(dependency rot)를 방지 할 수 있습니다. 어떤 고수준 구성요소가 저수준 구성요소에 의존하고, 그 저수준의 구성요소는 다시 고수준의 구성요소에 의존하는 것과 같은 식으로 의존성이 복잡하게 꼬여 있는 것을 의존성 부패라고 부릅니다.
이렇게 의존성이 부패되면 시스템이 어떤식으로 디자인 된 것인지 알아 볼 수 없습니다.
할리 우드 원칙을 사용하면 저수준 구성요소에서 시스템에 접속 할 수는 있지만 언제 어떤식으로 그 구성요소들을 사용할 지는 고수준의 구성요소에서 결정하게 됩니다.
즉, 고수준의 구성요소에서 "먼저 연락하지 마세요. 저희가 연락드리겠습니다" 라고 이야기 하는 것과 같습니다.
위 커피, 티 예제에서 CaffeinBeverageWithHook 클래스는 고수준의 구성요소입니다. 음료를 만드는 방법에 해당하는 알고리즘을 장악하고 메소드 구현이 필요한 상황에서만 서브클래스를 호출합니다.
서브클래스는 메소드의 구현만 담당하지 호출 당하기 전까지 추상클래스를 직접 호출하지 않습니다.
핵심정리
- 템플릿 메소드에서는 알고리즘의 단계들을 정의하는데 일부 단계는 서브클래스에서 구현하도록 할 수 있습니다.
- 템플릿 메소드 패던은 코드 재사용에 크게 도움이 됩니다.
- 템플릿 메소드가 들어 있는 추상클래스에서는 구상메소드, 추상메소드, 후크를 정의할 수 있습니다.
- 추상메소드는 서브클래스에서 구현합니다.
- 후크(hook)는 추상 클래스에 들어 있는 아무일도 하지 않거나 기본 행동을 정의하는 메소드로 서브클래스에서 오버라이드할 수 있습니다.
- 서브클래스에서 템플릿 메소드에 들어 있는 알고리즘을 함수보로 바꾸지 못하게 하고 싶다면 final 로 선언하면 됩니다.
- 헐리우드 원칙에 의하면 저수준 모듈은 언제 어떻게 호출할지는 고수준 모듈에서 결정하는 것이 좋습니다.
- 템플릿 메소드 패턴은 실전에서도 꽤 자주 쓰이지만 반드시 교과서적인 방식으로 적용되지는 않습니다.
- 스트래티지 패턴과 템플릿 메소드 패던은 모두 알고리즘을 캡슐화 하는 패턴이지만 전자에서는 상속을 후자에서는 구성을 이용합니다.
- 팩토리 메소드 패턴은 특화된 템플릿 메소드 패턴입니다.
전체 예제 소스 : https://github.com/JunpilPark/DesignPatternStudy/tree/master/TampleteMethod/src/main/java/com/example/template
참고 동영상 :
'Tech & Programming > Pattern & Design' 카테고리의 다른 글
팩토리 패턴(Factory Pattern) 이란? (0) | 2019.01.16 |
---|---|
프록시 패턴(proxy pattern) 이란? (0) | 2019.01.14 |
스테이트 패턴(State Pattern) 이란? (0) | 2019.01.11 |
이터레이터 패턴 (Iterator Pattern) 이란? (0) | 2019.01.10 |