Template Method Pattern
템플릿 메소드 패턴에 대해 정리합니다.
Template Method Pattern
개요
- 알고리즘의 구조(골격)를 메소드에 정의하고, 하위 클래스에서 알고리즘 구조의 변경없이 알고리즘을 재정의할 수 있게 하는 패턴.
- 상위 클래스에서 알고리즘의 구조를 정의하는 메소드를 템플릿 메소드라고 한다.
- 하위 클래스에서 템플릿 메소드를 구현하는 메소드를 프리미티브 메소드라고 한다.
- 상위 클래스에서 템플릿 메소드를 호출하면, 하위 클래스에서 구현한 프리미티브 메소드가 호출된다.
상위 클래스가 흐름 제어를 담당하고, 하위 클래스가 구체적인 작업을 담당하는 디자인 패턴
사용하는 경우
- 여러 클래스가 비슷한 알고리즘을 가지고 있고, 알고리즘의 구조를 변경하지 않고 알고리즘을 재정의하고 싶은 경우
- 알고리즘의 구조를 변경하지 않고 알고리즘을 재정의하고 싶은 경우
구성요소
- AbstractClass: 알고리즘의 구조를 정의하는 클래스
- ConcreteClass: 알고리즘을 구현하는 클래스
예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
class AbstractClass {
public:
void templateMethod() {
primitiveOperation1();
primitiveOperation2();
}
virtual void primitiveOperation1() = 0;
virtual void primitiveOperation2() = 0;
};
class ConcreteClassA : public AbstractClass {
public:
void primitiveOperation1() override {
std::cout << "ConcreteClassA::primitiveOperation1" << std::endl;
}
void primitiveOperation2() override {
std::cout << "ConcreteClassA::primitiveOperation2" << std::endl;
}
};
class ConcreteClassB : public AbstractClass {
public:
void primitiveOperation1() override {
std::cout << "ConcreteClassB::primitiveOperation1" << std::endl;
}
void primitiveOperation2() override {
std::cout << "ConcreteClassB::primitiveOperation2" << std::endl;
}
};
int main() {
AbstractClass* abstractClass = new ConcreteClassA();
abstractClass->templateMethod();
abstractClass = new ConcreteClassB();
abstractClass->templateMethod();
return 0;
}
템플릿 메서드와 전략 패턴의 조합
- 템플릿 메서드 패턴과 전략 패턴을 조합하여 사용할 수 있다.
대표적인 예로 스프링 프레임워크의 Template으로 끝나는 클래스들이 있다. (JdbcTemplate, RestTemplate, TransactionTemplate 등)
- Java TransactionTemplate 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class TransactionTemplate {
public <T> T execute(TransactionCallback<T> action) throws TransactionException {
// 일부 코드 생략
TransactionStatus status = this.transactionManager.getTransaction(this);
T result;
try {
result = action.doInTransaction(status);
} catch (RuntimeException ex) {
rollbackOnException(status, ex);
throw ex;
}
// 기타 코드 생략
this.transactionManager.commit(status);
return result;
}
}
void example() {
TransactionTemplate transactionTemplate = new TransactionTemplate();
transactionTemplate.execute(new TransactionCallback<String>() {
public String doInTransactionWithoutResult(TransactionStatus status) {
// 트랜잭션 벙위 내에서 실행할 코드
}
});
}
This post is licensed under CC BY 4.0 by the author.