본문 바로가기

디자인패턴

[디자인패턴] 템플릿 메서드 패턴

이번 글에서는 템플릿 메서드 패턴에 대해서 알아보려고 합니다.

  • 템플릿 메서드 패턴 개념
  • 사용예시
  • 템플릿 메서드 패턴 예제 코드
템플릿 메서드 패턴 개념

GOF 디자인패턴에서는 템플릿 메서드 패턴을 아래와 같이 정의하고 있습니다.

"작업에서 알고리즘의 골격을 정의하고 일부 단계를 하위 클래스로 연기합니다. 템플릿 메서드를 사용하면 하위 클래스가 알고리즘의 구조를 변경하지 않고도 알고리즘의 특정 단계를 재정의할 수 있습니다."

즉, 부모클래스에 전체적인 로직중 변경되지않는 부분과 변경되는 부분을 나누어 템플릿화 시키고 변경되는 부분을 서브클래스에 정의하는 방식입니다.

 

사용예시

나는 어느 회사에 개발자입니다. 회사의 여러 서비스 중 예약하는 서비스가 오래 걸린다는 말을 듣고, 개발팀장님이 해당 서비스가 실행되는데 걸리는 시간을 로그로 남겨달라고 요청을 하였습니다.

개발자인 저는 로직의 실행후시간 - 실행전시간을 계산하여 총 실행시간을 로그로 기록하였고, 어느 부분에서 실행시간이 오래걸리는지 알게되었습니다.

그 후로 개발팀장님은 모든 클래스에 로그를 남겨달라는 요구를 하였고, 개발자들은 많은 클래스에 똑같은 코드를 넣는다는 것은 효율적이지 못하다고 생각하여 템플릿 메서드 패턴을 사용하기로 하였습니다.

 

템플릿 메서드 패턴 예제 코드

그럼 로그를 남기기위해 서비스가 실행되고 종료될때까지의 걸린 시간을 로그로 찍어주는 예제코드를 만들어 보도록 하겠습니다.

현재 execute()메서드를 보면

  1. logStart()
  2. call()
  3. logEnd()
  4. resultTimePrinter()

1번, 3번, 4번은 실행시간을 출력해주기 위한 단순 반복되는 코드이고 2번만 실제 다른로직을 호출하는 코드입니다.

AbstractTemplate클래스에서는 변하지않는 logStart(), logEnd(), resultTimePrinter()사이에 변하는 로직인 call()을 조합하여 로그를 남기는 execute()라는 템플릿 메서드를 만들게 되었습니다.

@Test
void templateMethodV1() {
    AbstractTemplate template1 = new SubClassLogic1();
    AbstractTemplate template2 = new SubClassLogic2();
    template1.execute();
    template2.execute();
}
@Slf4j
public abstract class AbstractTemplate {

    public void execute() {
        long startTime = logStart();
        call();
        long endTime = logEnd();
        resultTimePrinter(startTime, endTime);
    }

    // 공통로직
    private long logStart() {
        long startTime = System.currentTimeMillis();
        return startTime;
    }

    // 공통로직
    private long logEnd() {
        long endTime = System.currentTimeMillis();
        return endTime;
    }

    // 공통로직
    private void resultTimePrinter(long startTime, long endTime) {
        log.info("resultTime={}", endTime - startTime);
    }

    // 변경되는 로직
    protected abstract void call();
}

@Slf4j
public class SubClassLogic1 extends AbstractTemplate {

    @Override
    protected void call() {
        log.info("비즈니스 로직1 실행");
    }
}

@Slf4j
public class SubClassLogic2 extends AbstractTemplate {

    @Override
    protected void call() {
        log.info("비즈니스 로직2 실행");
    }
}

자 이제 테스트코드를 실행해보도록 하겠습니다.
[logStart() => call() => logEnd() => resultTimePrinter()] 로직으로 진행되는 것을 알 수 있지만, 비즈니스 로직부분을 부모클래스에서 추상메서드로 선언하고 서브클래스에서 상속을 받아 메서드를 재정의함으로써 서로 다른 로직이 실행됨을 볼 수 있습니다.

 

 

즉, 템플릿메서드 패턴을 사용하여 반복되는 코드를 템플릿화시키고 변경되는 부분은 서브클래스로 상속받아 정의하게 함으로써 반복작업을 줄일 수 있는 엄청난 메리트를 얻게 될 수 있는게 바로 템플릿 메서드 패턴입니다.

'디자인패턴' 카테고리의 다른 글

[디자인패턴] 데코레이터 패턴  (1) 2021.11.27
[디자인패턴] 프록시 패턴  (0) 2021.11.24
[디자인패턴] 전략 패턴  (0) 2021.11.20