SW
[개발서적] 헤드퍼스트 디자인 패턴 Ch8. 템플릿 메소드 패턴 본문
템플릿 메소드
템플릿 메소드는 알고리즘의 각 단계를 정의하며, 서브클래스에서 일부 단계를 구현할 수 있도록 유도합니다.
추상 클래스 - CaffeineBeverage
abstract class CaffeineBeverage {
// 템플릿 메서드
final void prepareRecipe() {
boilWater();
brew();
pourInCup();
if (customerWantsCondiments()) {
addCondiments();
}
}
abstract void brew();
abstract void addCondiments();
void boilWater() {
System.out.println("물을 끓이는 중");
}
void pourInCup() {
System.out.println("컵에 따르는 중");
}
// Hook - 서브클래스에서 필요시 오버라이드
boolean customerWantsCondiments() {
return true;
}
}
Coffee 클래스
import java.util.Scanner;
public class Coffee extends CaffeineBeverage {
@Override
void brew() {
System.out.println("필터를 통해 커피를 우려내는 중");
}
@Override
void addCondiments() {
System.out.println("설탕과 우유를 추가하는 중");
}
@Override
boolean customerWantsCondiments() {
String answer = getUserInput("커피에 설탕과 우유를 넣어 드릴까요? (y/n): ");
return answer.toLowerCase().startsWith("y");
}
private String getUserInput(String prompt) {
System.out.print(prompt);
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
return input;
}
}
Tea 클래스
import java.util.Scanner;
public class Tea extends CaffeineBeverage {
@Override
void brew() {
System.out.println("찻잎을 우려내는 중");
}
@Override
void addCondiments() {
System.out.println("레몬을 추가하는 중");
}
@Override
boolean customerWantsCondiments() {
String answer = getUserInput("차에 레몬을 넣어 드릴까요? (y/n): ");
return answer.toLowerCase().startsWith("y");
}
private String getUserInput(String prompt) {
System.out.print(prompt);
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
return input;
}
}
메인 클래스
public class BeverageTestDrive {
public static void main(String[] args) {
CaffeineBeverage tea = new Tea();
CaffeineBeverage coffee = new Coffee();
System.out.println("\n차 준비 중:");
tea.prepareRecipe();
System.out.println("\n커피 준비 중:");
coffee.prepareRecipe();
}
}
- CaffeineBeverage 클래스:
- prepareRecipe() 메서드는 알고리즘의 골격을 정의하는 템플릿 메서드입니다. 이 메서드는 final로 선언되어 서브클래스에서 오버라이드할 수 없습니다.
- brew()와 addCondiments()는 추상 메서드로, 서브클래스에서 구체적으로 구현해야 합니다.
- customerWantsCondiments()는 후크(Hook) 메서드로, 기본적으로 true를 반환하며, 서브클래스에서 오버라이드하여 사용자의 입력에 따라 다른 행동을 하도록 할 수 있습니다. 후크(Hook)는 추상 클래스에서 선언되지만 기본적인 내용만 구현되어 있거나 아무 코드도 들어있지 않은 메소드입니다. 이러면 서브클래스는 다양한 위치에서 알고리즘에 끼어들 수 있습니다.
- Coffee 클래스:
- brew() 메서드에서는 커피를 우려내는 과정을 정의합니다.
- addCondiments() 메서드에서는 설탕과 우유를 추가하는 과정을 정의합니다.
- customerWantsCondiments() 후크 메서드를 오버라이드하여, 사용자가 설탕과 우유를 원하는지 물어보고 그에 따라 행동을 결정합니다.
- Tea 클래스:
- brew() 메서드에서는 차를 우려내는 과정을 정의합니다.
- addCondiments() 메서드에서는 레몬을 추가하는 과정을 정의합니다.
- customerWantsCondiments() 후크 메서드를 오버라이드하여, 사용자가 레몬을 원하는지 물어보고 그에 따라 행동을 결정합니다.
- BeverageTestDrive 클래스:
- Tea와 Coffee 객체를 생성하고, 각각의 prepareRecipe() 메서드를 호출하여 음료를 준비하는 전체 과정을 실행합니다.
템플릿 메서드 패턴은 알고리즘의 뼈대를 정의하고, 일부 단계를 서브클래스에서 재정의할 수 있게 하는 패턴입니다. 이 패턴을 통해 코드를 재사용하고, 알고리즘의 구조를 변경하지 않으면서 세부 구현을 다르게 할 수 있습니다.
주요 개념
- 템플릿 메서드(Template Method):
- 상위 클래스에 정의된 메서드로, 알고리즘의 전체 구조를 결정합니다.
- 이 메서드는 일련의 단계로 이루어져 있으며, 각 단계는 메서드 호출로 표현됩니다.
- 일부 단계는 서브클래스에서 구현해야 하는 추상 메서드로 정의됩니다.
- 추상 메서드(Abstract Method):
- 템플릿 메서드 내에서 호출되며, 서브클래스에서 구체적으로 구현해야 합니다.
- 예: brew()와 addCondiments() 메서드는 서브클래스에서 구체적으로 정의해야 하는 단계입니다.
- 후크(Hook):
- 후크는 선택적으로 오버라이드할 수 있는 메서드입니다. 기본 구현을 제공하지만, 서브클래스에서 필요에 따라 변경할 수 있습니다.
- 후크를 통해 알고리즘의 특정 단계를 실행할지 말지를 결정하거나, 기본 동작을 변경할 수 있습니다.
- 예: customerWantsCondiments()는 후크로 사용자가 추가 재료를 원하는지 여부를 확인할 수 있게 합니다.
- 상속을 통한 확장:
- 템플릿 메서드 패턴은 상속을 통해 기능을 확장합니다. 상위 클래스에 정의된 템플릿 메서드를 그대로 사용하면서, 하위 클래스에서 구체적인 동작을 변경할 수 있습니다.
템플릿 메서드 패턴의 장점
- 코드 재사용성: 알고리즘의 공통 부분을 상위 클래스에서 정의하여 코드 중복을 줄일 수 있습니다.
- 알고리즘의 안정성 유지: 템플릿 메서드는 상위 클래스에서 정의되어 알고리즘의 기본 구조를 변경하지 않으면서, 서브클래스에서 세부 구현을 다르게 할 수 있습니다.
- 유연성: 후크 메서드를 통해 서브클래스에서 알고리즘의 동작을 필요에 따라 변경할 수 있습니다.
- 확장성: 새로운 서브클래스를 추가함으로써 알고리즘의 새로운 변형을 쉽게 구현할 수 있습니다.
템플릿 메서드 패턴 사용 시 고려 사항
- 상속을 통한 확장이라는 구조적 특성 때문에 모든 서브클래스가 상위 클래스의 알고리즘에 의존하게 됩니다. 따라서 상위 클래스의 변경이 서브클래스에 영향을 미칠 수 있습니다.
- 후크 메서드를 제공함으로써 알고리즘의 유연성을 높일 수 있지만, 후크 메서드를 너무 많이 제공하면 서브클래스의 복잡성이 증가할 수 있습니다.
템플릿 메서드 패턴은 알고리즘의 핵심 구조를 보호하면서도 확장 가능하게 유지할 수 있는 강력한 디자인 패턴입니다.
'개발서적 > 헤드퍼스트 디자인패턴' 카테고리의 다른 글
[개발서적] 헤드퍼스트 디자인 패턴 Ch10. 상태 패턴 (0) | 2024.09.22 |
---|---|
[개발서적] 헤드퍼스트 디자인 패턴 Ch9. 반복자 패턴과 컴포지트 패턴 (0) | 2024.09.04 |
[개발서적] 헤드퍼스트 디자인 패턴 Ch7. 어댑터 패턴과 퍼사드 패턴 (1) | 2024.08.29 |
[개발서적] 헤드퍼스트 디자인 패턴 Ch6. 커맨드(Command) 패턴 (0) | 2024.08.15 |
[개발서적] 헤드퍼스트 디자인 패턴 Ch5. 싱글턴(Singleton) 패턴 (0) | 2024.08.12 |
Comments