mojo's Blog
Template Method Pattern 본문
Template Method Pattern
목적: 알고리즘의 프레임워크를 식별하여 클래스를 구현하여 실제 동작을 정의할 수 있도록 함
사용 시기
- 알고리즘의 단일 추상적 구현이 필요함
- 하위 클래스 간에 공통된 동작은 공통 클래스에 국한되어야 함
- 부모 클래스는 하위 클래스의 동작을 균일하게 호출할 수 있어야 함
- 대부분 또는 모든 하위 클래스는 동작을 구현해야 함
두 클래스를 살펴보도록 한다.
※ Class Philosopher
public class Philosopher {
void prepareEat() {
think();
leftHandup();
rightHandup();
eat();
}
public void think() { // impl think }
public void leftHandup() { // impl leftHand }
public void rightHandup() { // impl rightHand }
public void eat() { // impl eat }
}
철학자의 먹는 순서
(1) 생각을 함
(2) 왼쪽 손을 듬
(3) 오른쪽 손을 듬
(4) 먹음
※ Class Scientist
public class Scientist {
void prepareEat() {
think();
rightHandup();
leftHandup();
eat();
}
public void think() { // impl think }
public void leftHandup() { // impl leftHand }
public void rightHandup() { // impl rightHand }
public void eat() { // impl eat }
}
과학자의 먹는 순서
(1) 생각을 함
(2) 오른쪽 손을 듬
(3) 왼쪽 손을 듬
(4) 먹음
철학자와 과학자는 손을 드는 순서가 변경되었다. (그 외 과정은 동일)
두 코드는 클래스 간에 중복된다.
클래스를 더 추가할 수록 먹는 방식이 달라져 중복이 더 발생할 수 있으며,
알고리즘 및 구현에 대한 지식은 클래스에 분산되어 진다.
※ Abstracting prepareEat()
public abstract class Person {
final void prepareEat() {
think();
handsUp();
eat();
}
abstract void handsUp();
public void think() { // impl think }
public void eat() { // impl eat }
}
public class Philosopher extends Person {
public void handsUp() {
// impl leftHand
// impl rightHand
}
}
public class Scientist extends Person {
public void handsUp() {
// impl rightHand
// impl leftHand
}
}
사람마다 손드는 방식이 다르며 그 외 생각, 먹기 순서가 동일하다고 하다면 위와 같이 추상 클래스를 만들 수 있다.
추상 메서드 handsUp 를 둬서 사람마다 handsUp 를 오버라이딩한다면 중복 코드를 방지할 수 있다.
prepareEat() 메서드는 템플릿 메서드라고 불린다.
※ More General Approach
변경사항
- 두 하위 클래스 모두 일반 알고리즘을 상속함 (생각 -> 손들기 -> 먹기)
- 알고리즘의 일부 방법은 모든 하위 클래스에 대해 동일한 작업을 수행하는 구체적인 방법임 (생각, 먹기)
- 알고리즘의 다른 방법은 추상적이며, 클래스 별 작업을 수행하는 방법임 (손들기)
장점
- 단일 클래스는 알고리즘, 즉 Person의 생각, 먹기 알고리즘을 보호하고 제어함
- 슈퍼 클래스는 방법의 재사용을 용이하게 함
- 코드 변경은 한 곳에서만 발생함 (손 들기)
- 철학자, 과학자 외에 다른 사람들을 쉽게 추가할 수 있음 (손 들기만 변경한다면)
※ Template Method Pattern
- prepareEat() 는 템플릿 메서드 패턴을 구현함
- 알고리즘, 즉 먹는 것을 준비하기 위한 템플릿 역할을 함
- 템플릿에서 각 단계는 메서드로 표시되어짐 (생각, 손들기, 먹기 등)
- 일부 방법은 슈퍼 클래스에서 구현되며, 다른 방법은 하위 클래스에서 구현되며 추상적으로 선언됨
※ Hook Method
Hook는 추상 클래스에서 선언되지만 비어있거나 기본 구현만 제공되는 메서드이다.
하위 클래스가 원하는 경우 다양한 지점에서 알고리즘을 "Hook" 할 수 있는 기능을 제공한다.
또한 하위 클래스는 후크를 무시할 수 있다.
public abstract class Person {
final void prepareEat() {
think();
if (personWantsHandsUp()) handsUp();
eat();
}
abstract void handsUp();
public void think() { // impl think }
public void eat() { // impl eat }
boolean personWantsHandsUp() {
return true;
}
}
public class Philosopher extends Person {
public void handsUp() {
// impl leftHand
// impl rightHand
}
public boolean personWantsHandsUp() {
String answer = getUserInput();
return answer.toLowerCase().startsWith("y");
}
}
위와 같이 철학자가 y 를 말하면 왼손, 오른손을 들고 y 를 말하지 않으면 손을 들지 않을 수 있다.
※ Template Method Pattern vs. Strategy Pattern
Template Method는 상속을 이용하여 알고리즘의 일부를 변경한다.
Strategy는 delegation을 사용하여 전체 알고리즘을 변경한다.
'Design Patterns' 카테고리의 다른 글
Mediator Pattern (0) | 2024.06.06 |
---|---|
State Pattern (0) | 2024.06.06 |
Observer Pattern (1) | 2024.06.06 |
Strategy Pattern (0) | 2024.06.06 |
GRASP (1) | 2024.05.15 |