템플릿 메서드 패턴이란?
💡 특정 작업을 처리하는 일부분을 서브 클래스로 캡슐화하여 전체적인 구조는 바꾸지 않으면서 특정 단계에서 수행하는 내용을 바꾸는 패턴입니다
우리가 흔히 패턴이라고 인식하지 않고 쓰는 패턴이다.
라면을 끓이는 단계를 템플릿 메서드 패턴의 예시로 들어보겠습니다.
public abstract class RamenRecipe {
final void prepareRamen() {
preparePot() // 냄비 준비
boilWater(); // 물을 끓이기
putBasicMaterial(); // 기본 면, 스프 넣기
if(addMore()) {
addIngredient(); // 더 넣고 싶은 것 넣기
}
}
void preparePot() {
System.out.println("냄비 준비");
}
boolean addMore() {
return false;
}
abstract void boilWater();
abstract void putBasicMaterial();
abstract void addIngredient();
}
public class MyRamenRecipe extends RamenRecipe {
@Override
abstract void boilWater() {
System.out.println("물을 정량보다 조금 넣어야지");
}
@Override
abstract void putBasicMaterial() {
System.out.println("면을 넣은 후에 스프를 넣는다.");
}
@Override
abstract void addIngredient() {
System.out.println("달걀과 만두를 넣어야겠어.");
}
}
인터페이스로 템플릿 메서드 패턴을 구현해도 되지 않을까?
템플릿 메서드는 기본적으로 동작 과정의 순서는 고정해놓고 각 동작 과정마다 세부적인 변화를 줄 수 있게 하는 것이 목적이다. 위의 예시에서 보자면, 라면을 끓일 때 냄비를 준비하고 물을 끓이고 기본 재료들을 넣는 순서는 지켜져야한다. 그렇기에 그 순서를 정해주는 메서드는 final 로 지정해주었다. 인터페이스의 디폴트 메시지로 대체한다면 어떻게 될까? 변하지 말아야하는 동작 순서를 재정의 할 수 있게 된다. 물을 끓이기도 전에 면과 스프를 넣게 만들수도 있다는 의미이다.
또한 인터페이스에서는 선언된 메서드가 public abstract 이다. 추상클래스는 접근 제어자를 이용하여서 외부에서의 호출을 막을 수 있지만 인터페이스는 의도하지 않은 외부 접근을 허용한다.
그렇다면, 인터페이스를 이용한 구현은 쓰면 안되는 걸까? 템플릿 메서드를 추상클래스에서 구현한다면 상속 받은 서브클래스는 이미 하나의 클래스를 상속 받았기 때문에 다른 클래스를 상속 받을 수 없지만, 인터페이스에서 구현했다면 다른 클래스를 상속 받을 수도 있다.
뭐가 옳은지를 따지기보다는 내가 의도하고자 하는 바에 따라서 선택하면 되는 문제인 것 같다.
'이론 > 디자인패턴' 카테고리의 다른 글
추상 팩토리 패턴 (0) | 2022.12.06 |
---|---|
팩토리메서드 패턴 (0) | 2022.12.04 |
어뎁터 패턴 (0) | 2022.12.02 |
데코레이터 패턴 (0) | 2022.11.26 |
프록시 패턴 (0) | 2022.11.25 |