FireDrago
[객체지향과 디자인패턴] 템플릿 메서드 패턴 본문
템플릿 메서드 패턴 (Template Method Pattern)
상위 클래스에서 실행 과정의 구조를 정의하고,
하위 클래스에서 개별 단계의 세부 구현을 변경하여 사용하는 디자인 패턴이다.
코드의 중복을 줄이고 재사용성을 높일 수 있다.
실행 과정/ 단계는 동일한데 각 단계 중 일부의 구현이 다른 경우에 사용할 수 있는 패턴이다.
템플릿 메서드 패턴은 두가지 클래스가 필요하다.
1. 실행 과정을 구현한 상위 클래스
2. 실행 과정의 일부 단계를 구현한 하위 클래스
// 실행과정을 구현한 상위 클래스
public abstract class Authenticator {
// 인증확인, 예외처리, 인증성공의 공통된 과정을 정의한다.
public Auth authenticate(String id, String pw) {
if (!doAuthenticate(id, pw)) {
throw createException();
}
return createAuth(id);
}
// 인증 확인 과정을 추상 메서드로 구현했다. 세부 구현은 달라질 수 있다.
protected abstract boolean doAuthenticate(String id, String pw);
// 인증 실패시, 예외발생
private RuntimeException createException() {
throw new AuthException();
}
// 인증 성공 과정을 추상 메서드로 구현했다.
protected abstract Auth createAuth(String id);
}
위 코드에서 Authenticator 클래스는 인증 흐름을 정의하고, 인증 확인 및 성공 처리를 하위 클래스에서 구현하도록 한다.
// 실행과정을 구현한 상위 클래스
public abstract class Authenticator {
// 인증확인, 예외처리, 인증성공의 공통된 과정을 정의한다.
public Auth authenticate(String id, String pw) {
if (!doAuthenticate(id, pw)) {
throw createException();
}
return createAuth(id);
}
// 인증 확인 과정을 추상 메서드로 구현했다. 세부 구현은 달라질 수 있다.
protected abstract boolean doAuthenticate(String id, String pw);
// 인증 실패시, 예외발생
private RuntimeException createException() {
throw new AuthException();
}
// 인증 성공 과정을 추상 메서드로 구현했다.
protected abstract Auth createAuth(String id);
}
템플릿 메서드 패턴을 통해 코드의 중복 문제를 제거하면서 코드를 재사용할 수 있게된다.
예를들어 DB를 사용한 인증을 추가하고 싶다면, DbAuthenticator 구현 클래스를 만들면 된다.
이때에도 클라이언트는 그대로 Authenticator를 사용할 수 있다.
LdapAuthenticator 클래스는 일부과정의 구현만을 제공한다.
전체 실행과정은 상위타입인 Authenticator의 authenticate() 메서드에서 제공하게 된다.
상위 클래스가 흐름 제어의 주체
템플릿 메서드 패턴에서는 상위 타입의 템플릿 메서드가 모든 실행 흐름을 제어한다.
하위 타입의 메서드는 템플릿 메서드에서 호출되는 구조를 가질수도 있다.
public abstract class AsyncTask<Params, Progress, Result> {
public AsyncTask() {
...
return postResult(doInBackground(mParams));
}
public final AsyncTask<Params, Progress, Result> executeOnExecutor
(Executor exec, Params... params) {
...
onPreExecute();
return this;
}
// 반드시 오버라이딩으로 구현해야하는 메서드
protected abstract Result doInBackground(Params... params);
// 필요한 경우만 재정의 해서 사용할 수 있다.
protected void onPreExecute() {
...
}
}
템플릿 메서드와 전략 패턴의 조합
템플릿 메서드에서 전체 실행 흐름은 고정되어 있고, 실행 과정의 일부 동작(전략)을 파라미터로 전달받아 실행하는 구조
// 템플릿 메서드를 실행할때, 파라미터를 통해 변경부분을 전달받는다.
public <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;
}
위 메서드에서 TransactionCallback<T>는 전략 패턴의 역할을 한다.
execute 메서드는 트랜잭션 처리의 틀을 제공하며, 구체적인 트랜잭션 내 동작은 action 객체가 수행한다.
// 위 메서드를 사용하는 코드
transactionTemplate.execute(new TransactionCallback<String>() {
public String doInTransaction(TransactionStatus status) {
// 트랜잭션 범위 안에서 실행될 코드
}
});
템플릿 메서드 패턴과 전략 패턴은 서로 조합하여 사용할 수 있다.
실행 과정의 일부 단계를 전략 패턴의 인스턴스로 전달받아 처리하게 함으로써, 더욱 유연함을 가진다.
'프로그래밍 > 디자인패턴' 카테고리의 다른 글
| [객체지향과 디자인패턴] 옵저버 패턴 (0) | 2024.09.25 |
|---|---|
| [객체지향과 디자인패턴] 어댑터 패턴 (0) | 2024.09.23 |
| [객체지향과 디자인패턴] 전략패턴 (0) | 2024.09.06 |
| [객체지향과 디자인패턴] 6장 DI와 서비스 로케이터 - (1) (0) | 2024.09.04 |
| [객체지향과 디자인패턴] 5장 객체지향 설계 원칙 SOLID (2) (0) | 2024.09.02 |
