템플릿 메소드 패턴
Written by niee on
정의
- 서로 다른 클래스들의 알고리즘이 공통될 때(상세 기능이 아닌 일반적인 관점에서) 공통된 알고리즘을 슈퍼클래스에서 정의하고 일부 다른부분은 추상 메소드로 정의하여 서브클래스에서 구현하는 패턴
템플릿 메소드 패턴의 특징
- 코드의 재사용에 크게 도움된다.
- 클래스간의 의존성을 낮춰준다.
- 프레임워크를 만들때 자주 사용되는 패턴이다.
- 변경이 일어나지 않는 부분은 슈퍼 클래스에서 final로 지정하여 오버라이드하지 못하게 막는다
템플릿 메소드 디자인 원칙(책에서는 헐리우드 원칙이라 나옴)
- 저수준 구성요소가 고수준의 구성요소를 직접 호출할 수 없다.(고수준의 구성요소에서 호출하기전에 저수준 구성요소는 대기한다.)
- 클래스의 주요 기능은 고수준 구성요소에서 장악하고 구현이 필요한 기능만 저수준 클래스를 호출한다.
- 클래스의 구성요소들의 사용은 고수준 구성요소(템플릿을 가진 슈퍼클래스를 말하는듯)에서 결정한다.
- 저수준 구성요소(템플릿에서 추상메소드로 정의한 메소드를 상세구현한 자식 클래스)는 고수준 구성 요소를 직접 호출할수 없다.
- 이 원칙이 위반되면 클래스간의 의존도가 매우 높아진다.
서로 다른 종류의 DB 조회 적용 예제
- 오라클/mysql/mssql….등등 하나의 어플리케이션에서 여러대의 DB에 select쿼리를 사용 한다고 가정.
- 템플릿 메소드 패턴을 사용하지 않고 가져올 경우 아래의 코드를 각 클래스마다 사용해야함
public class OracleSelect {
public void getSelect(){
try{
System.out.println("Oracle Driver Loading");
}catch(Exception e){
System.out.println("Oracle Driver Loading Exception");
}
try{
System.out.println("Oracle getConnection");
System.out.println("Oracle createStatement");
System.out.println("Oracle executeQuery");
}catch(Exception e){
System.out.println("Oracle Exception");
}finally{
System.out.println("Oracle Resource Close");
}
}
}
템플릿 메소드의 적용
- 각 DB연결후 쿼리를 가져오는 부분에서 사용되는 기능들을 일반적인 관점으로 공통화 시킨다.
- 오라클 드라이버를 로딩한다./My-sql 드라이버를 로딩한다.(x) -> DB드라이버를 로딩한다.
- 오라클 커넥션을 가져온다./My-sql 커넥션을 가져온다.(x) -> 커넥션을 가져온다.
- 오라클 statement을 생성한다./My-sql statement을 생성한다.(x) -> statement을 생성한다.
- 오라클에 select 쿼리를 날린다./My-sql에 select 쿼리를 날린다.(x) -> select 쿼리를 날린다.
- 오라클에 사용된 리소스를 close한다./My-sql에 사용된 리소스를 close한다.(x) -> 리소스를 close한다.
- 공통화 시킨 기능을 토대로 템플릿으로 사용될 기능에서 변경이 안되는 부분, 변경될 부분을 분리하여 변경이 안되는 부분은 final로 변경되는 부분은 추상메소드로 기능을 정의한다.
- 적용 예
//템플릿으로 사용될 부분
public abstract class DBSelectTemplate {
final void getSelect(String dbName,String query){
try{
driverLoading(dbName);
}catch(Exception e){
System.out.println(dbName + " Driver Loading Exception");
}
try{
getConnection(dbName);
createStatement(dbName);
executeQuery(query);
}catch(Exception e){
System.out.println(dbName + " Exception");
}finally{
resourceClose(dbName);
}
}
//1.DB드라이버를 로딩한다.
final void driverLoading(String dbName){
System.out.println(dbName + " Driver Loading");
}
//2.커넥션을 가져온다.
final void getConnection(String dbName){
System.out.println(dbName + " getConnection");
}
//3.statement을 생성한다.
final void createStatement(String dbName){
System.out.println(dbName + " createStatement");
}
//4.select 쿼리를 날린다.
abstract void executeQuery(String query);
//5.리소스를 close한다.
final void resourceClose(String dbName){
System.out.println(dbName + " Resource Close");
}
}
public class MysqlSelectUseTemplate extends DBSelectTemplate{
@Override
void executeQuery(String query) {
// TODO Auto-generated method stub
System.out.println("Mysql ==> " + query);
}
}
결과
- 공통된 부분을 분리하여 적용함으로써 코드의 재사용율이 높아졌다.
템플릿 메소드가 사용된곳을 생각해보자
- 샘플소스확인
- 실전 패턴 적용이 교재에 나온 내용과 완전히 일치할 수 없다. 주어진 상황과 제약 조건에 맞추어 적용할 수 있어야한다. ex)Arrays.sort()
Comments