템플릿 메소드 패턴
위키피디아
설명 및 스도코드
- 부모 클래스에서 알고리즘의 골격을 정의하지만, 해당 알고리즘의 구조를 변경하지 않고 자식 클래스들이 알고리즘의 특정 단계들을 오버라이드(재정의)할 수 있도록 하는 행동 디자인 패턴
템플릿 메소드의 구조
![](https://velog.velcdn.com/images/_hoya_/post/5ec0a797-5dae-43cb-8e84-7af244c2e156/image.png)
- 추상 클래스(Abstract Class)
- 알고리즘의 단계들의 역할을 하는 메서드들을 선언하며, 이러한 메서드를 특정 순서로 호출하는 실제 템플릿 메소드도 선언
- 단계들은 Abstract로 선언되거나 일부 디폴트 구현을 갖는다
- 구상 클래스(Concrete Class)
- 모든 단계들을 오버라이드할 수 있지만 템플릿 메서드 자체는 오버라이드할 수 없다
템플릿 메소드의 적용
- 클라이언트들이 알고리즘의 특정 단계들만 확장할 수 있도록 하고 싶을 때, 그러나 전체 알고리즘이나 알고리즘 구조는 확장하지 못하도록 하려고 할 때 사용
- 템플릿 메서드는 모놀리식 알고리즘을 일련의 개별 단계들로 전환할 수 있도록 한다.
- 이 알고리즘은 부모 클래스에서 정의된 구조를 그대로 유지하면서 자식 클래스들에 의해 쉽게 확장될 수 있다.
- 약간의 차이가 있지만 거의 같은 알고리즘들을 포함하는 여러 클래스가 있는 경우에 사용
- 알고리즘이 변경되면 모든 클래스를 수정해야 할 수도 있다.
- 이러한 알고리즘을 템플릿 메서드로 전환하면 유사한 구현들이 있는 단계들을 부모 클래스로 끌어올릴 수 있으며, 그로 인해 코드 중복을 제거할 수 있다.
- 자식 클래스 중 서로 코드가 다른 부분들은 자식 클래스들에 남겨놓을 수 있다.
다른 패턴과의 관계
- 팩토리 메서드는 템플릿 메서드의 특수화라고 생각할 수 있다. 동시에 대규모 템플릿 메서드의 한 단계의 역할을 팩토리 메서드가 할 수 있다.
- 템플릿 메서드는 상속을 기반으로 한다. 이 메서드는 자식 클래스들에서 알고리즘의 부분들을 확장하여 변경할 수 있도록 한다.
- 전략 패턴은 합성을 기반으로 한다. 객체 행동의 일부분들을 이러한 행동에 해당하는 다양한 전략들을 제공하여 변경할 수 있다.
- 템플릿 메서드는 클래스 수준에서 작동하므로 정적이다. 전략 패턴은 객체 수준에서 작동하므로 런타임에 행동들을 전환할 수 있도록 한다.
템플릿 메소드 패턴 예제
public abstract class Coffee {
final void makeCoffee() {
boilWater();
putEspresso();
putIce();
putExtra();
}
// SubClass에게 확장/변화가 필요한 코드만 코딩하도록 한다.
abstract void putExtra();
// 공통된 부분은 상위 클래스에서 해결하여 코드 중복을 최소화 시킨다.
private void boilWater() {
System.out.println("물을 끓인다.");
}
private void putEspresso() {
System.out.println("끓는 물에 에스프레소를 넣는다.");
}
private void putIce() {
System.out.println("얼음을 넣는다.");
}
}
public class IceAmericano extends Coffee{
@Override
void putExtra() {
System.out.println("시럽을 넣는다.");
}
}
package TemplateMethodPattern;
public class IceLatte extends Coffee{
@Override
void putExtra() {
System.out.println("우유를 넣는다.");
}
}
public class CoffeeMain {
public static void main(String[] args) {
IceAmericano americano = new IceAmericano();
IceLatte latte = new IceLatte();
americano.makeCoffee();
System.out.println("===");
latte.makeCoffee();
}
}