9. 템플릿 메서드 패턴

템플릿 메서드 패턴

템플릿 메서드 패턴은 특정 역할의 책임을 한 메서드에 여러 메서드를 조합*(이게 템플릿!)*으로 정해놓는 패턴이다.

템플릿 메서드를 구성하는 메서드들은 역할에 속하는 객체마다 다르게 구현될 수 있다.

활용 예시

우리는 여러 DB에 연결해야 한다.

우리가 연결한 DB는 모두 다음과 같은 절차를 따른다고 하자.
해당 DB드라이버 찾기 - DB에 로그인 - DB에 연결

이때 DB마다 사용하는 드라이버가 다르다.

이 상황에서 템플릿 메서드 패턴을 활용해서 문제를 해결해보자.

템플릿 메서드를 포함한 추상 클래스

일단 추상 클래스 안에 주어진 템플릿을 구현한 메서드를 만들어보자!
이때 각 DB마다 달라지는 부분은 추상 메서드로 다형성을 확보한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public abstract class DataConnection {
//템플릿 메서드
public final void process() {
findDriver();
login();
connectDB();
}

public abstract void findDriver();
public abstract void connectDB();

public final void login() {
System.out.println("로그인을 실행합니다...");
}
}

추상 클래스를 상속하는 자식 클래스

이제 DB마다 클래스를 상속해서 구현하자.
추상 메서드를 DB 요구 조건에 맞게 구현하면 된다.

우리는 MySQL과 H2를 예시로 구현해보자

1
2
3
4
5
6
7
8
9
10
11
public class MySQLConnection extends DataConnection{
@Override
public void findDriver() {
System.out.println("MySQL 드라이버를 찾습니다.");
}

@Override
public void connectDB() {
System.out.println("MySQL과 연결합니다.");
}
}
1
2
3
4
5
6
7
8
9
10
11
public class H2Connection extends DataConnection{
@Override
public void findDriver() {
System.out.println("H2 드라이버를 찾습니다.");
}

@Override
public void connectDB() {
System.out.println("H2 드라이버를 연결합니다.");
}
}

결과 확인

이제 적용해보자.

1
2
3
4
5
6
7
8
9
public class Application {
public static void main(String[] args) {
DataConnection dataConnection = new MySQLConnection();
dataConnection.process();

dataConnection = new H2Connection();
dataConnection.process();
}
}
1
2
3
4
5
6
MySQL 드라이버를 찾습니다.
로그인을 실행합니다...
MySQL과 연결합니다.
H2 드라이버를 찾습니다.
로그인을 실행합니다...
H2 드라이버를 연결합니다.

템플릿 메서드 패턴의 문제

템플릿 메서드 패턴은 확장이 필요할 때마다 새로운 클래스를 상속해서 추가해줘야 한다. 그리고 상속이 가지는 단점을 그대로 가져온다. 컴파일 타임에 고정된 관계가 정해진다. 전략 패턴은 더 유연하게 확장할 수 있다.

템플릿 메서드 패턴은 DIP 원칙을 일부 어길 수 있다. DIP는 상위 모듈은 하위 모듈에 의존을 금지하고 서로 추상화된 인터페이스에 의존하라는 원칙이다.
그런데 템플릿 메서드 패턴은 만약 추상 클래스가 상위 모듈(즉 사용하는 측)이고 구현체가 특정 로직을 구현한 하위 모듈인 방식으로 구현하면 구현체가 상위 모듈을 의존하게 된다.

스프링의 템플릿 콜백과의 차이점?

둘 다 템플릿을 사용해서 변경 주기가 다른 코드를 분리하지만, 템플릿 콜백은 템플릿에서 메서드를 실행할 때 인자로 콜백 함수를 받아서 수행하는 일종의 전략 패턴이다. 즉 상속으로 확장하는 템플릿 메서드보다 더 유연하다. 템플릿 콜백은 JdbcTemplate와 같은 스프링의 여러 곳에서 사용된다. 템플릿 콜백은 템플릿과 콜백 사이의 경계를 어떻게 지을 것인지, 그리고 만들어지는 콜백들이 또 특정한 패턴이 생기면 그 코드를 템플릿에 모아둘 수 있는지 점검해봐야 한다.

Share