1. 템플릿 메서드 패턴 개요
- 템플릿 메서드 패턴은 객체지향 설계의 핵심 원칙인 "변하는 것과 변하지 않는 것을 분리"하는 것을 실현하는 고전적인 디자인 패턴입니다.
1.1 핵심 개념
- 알고리즘의 골격을 부모 클래스에 정의합니다.
- 변경이 필요한 부분만 자식 클래스에서 구현합니다.
- 전체 알고리즘 구조는 유지하면서 특정 단계만 변경 가능합니다.
정보
GOF의 정의: "작업에서 알고리즘의 골격을 정의하고 일부 단계를 하위 클래스로 연기합니다. 템플릿 메서드를 사용하면 하위 클래스가 알고리즘의 구조를 변경하지 않고도 알고리즘의 특정 단계를 재정의할 수 있습니다."
1.2 패턴의 구조
- 추상 클래스: 알고리즘의 뼈대 정의
- 구체 클래스: 실제 비즈니스 로직 구현
- 훅(Hook) 메서드: 선택적으로 오버라이딩 가능한 메서드
2. 템플릿 메서드 패턴 구현
2.1 추상 클래스 정의
public abstract class AbstractTemplate<T> {
private final LogTrace trace;
public AbstractTemplate(LogTrace trace) {
this.trace = trace;
}
// 템플릿 메서드: 알고리즘의 골격 정의
public T execute(String message) {
TraceStatus status = null;
try {
status = trace.begin(message);
// 변하는 부분(자식 클래스에서 구현)
T result = call();
trace.end(status);
return result;
} catch (Exception e) {
trace.exception(status, e);
throw e;
}
}
// 추상 메서드: 자식 클래스에서 반드시 구현
protected abstract T call();
}
- AbstractTemplate는 템플릿 메서드인
execute()
를 정의합니다. execute()
메서드는 알고리즘의 골격을 정의하고,call()
메서드를 호출합니다.call()
메서드는 추상 메서드로, 자식 클래스에서 반드시 구현해야 합니다.- 이 메서드는 구체 클래스에서 실제 비즈니스 로직을 구현합니다.
- 구체 클래스마다 서로 다른 로직을 수행할 수 있습니다.
2.2 구체 클래스 구현
@Slf4j
public class SubClassLogic1 extends AbstractTemplate {
@Override
protected void call() {
log.info("비즈니스 로직1 실행");
}
}
- 구체 클래스는 추상 클래스를 상속받아
call()
메서드를 구현합니다. call()
메서드는 구체 클래스마다 다른 비즈니스 로직을 수행할 수 있습니다.- 템플릿 메서드 패턴을 통해 알고리즘의 구조는 유지하면서 특정 단계만 변경할 수 있습니다.
3. 패턴 활용하기
3.1 일반적인 상속 방식
@Slf4j
public class OrderService extends AbstractTemplate<String> {
@Override
protected String call() {
// 구체적인 비즈니스 로직 구현
return "order processed";
}
}
- 위 코드는 가장 일반적인 상속 방식으로 템플릿 메서드 패턴을 활용합니다.
- OrderService는 AbstractTemplate을 상속받아
call()
메서드를 구현합니다.
3.2 익명 클래스 활용
@RestController
@RequiredArgsConstructor
public class OrderController {
private final OrderService orderService;
private final LogTrace trace;
@GetMapping("/request")
public String request(String itemId) {
AbstractTemplate<String> template = new AbstractTemplate<>(trace) {
@Override
protected String call() {
orderService.orderItem(itemId);
return "ok";
}
};
return template.execute("OrderController.request()");
}
}
- 익명 클래스를 활용하면 템플릿 메서드 패턴을 더 유연하게 활용할 수 있습니다.
- OrderController에서는 AbstractTemplate을 익명 클래스로 구현하여 사용합니다.
4. 장단점 분석
4.1 장점
- 코드 중복 제거
- 알고리즘의 구조 유지
- 유지보수성 향상
- 확장성 확보