템플릿 메서드 패턴이란?

JooHeon·2021년 12월 2일
0

🖊 목적

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

🖊 스프링이 자주 사용하는 디자인 패턴 중 하나

로직의 핵심 기능과 부가 기능(로그, 트랜잭션 등)을 모듈화해서 분리하는 방법이다.

🖊 어떤 경우에 왜 사용할까?

여러개의 클래스에 로그를 남겨야 한다고 가정할 때
각 비지니스 로직에 로그를 남기는 부가 기능을 작성하는 건 비효율적이고 코드가 지저분해진다.
이러한 경우에 변하는 부분과 변하지 않는 부분을 모듈화해서 분리해내 효율적으로 처리할 수 있다.

🖊 사용법

클래스에 변하지 않는 것(부가 기능)을 execute() 메소드에 몰아넣는다.
이러면 이것이 템플릿이 되고 변하는 부분(핵심 기능)은 call() 메서드를 호출해서 처리한다.
변하지 않는 것은 부모 클래스로 두고, 자식 클래스에 변하는 부분을 둬 상속과 오버라이딩을 사용해서 처리한다.

🖊 예제

//부모 클래스
@Slf4j
public abstract class AbstractTemplate {

    public void execute(){
        long startTime = System.currentTimeMillis();
        //비지니스 로직 실행
        call();
        //비지니스 로직 종료
        long endTime = System.currentTimeMillis();
        long resultTime = endTime - startTime;
        log.info("resultTime={}", resultTime);
    }

    protected abstract void call();
}


//자식 클래스
@Slf4j
public class SubClassLogic1 extends AbstractTemplate{
    @Override
    protected void call() {
        //비지니스 로직 실행
        log.info("비지니스 로직1 실행");
        //비지니스 로직 종료
    }
}


//테스트 메서드
@Test
    void templateMethodV1(){
        AbstractTemplate template1 = new SubClassLogic1();
        AbstractTemplate template2 = new AbstractTemplate() {
            @Override
            protected void call() {
                //비지니스 로직 실행
                log.info("비지니스 로직2 실행");
                //비지니스 로직 종료
            }
        };

        template1.execute();
        template2.execute();
    }
    
    
// 결과
SubClassLogic1 - 비지니스 로직1 실행
AbstractTemplate - resultTime=6
SubClassLogic2 - 비지니스 로직2 실행
AbstractTemplate - resultTime=1

🖊 문제점

상속에서 오는 단점을 그대로 안고간다.
자식 클래스가 부모 클래스와 컴파일 시점에 강하게 결합되는 문제가 있다.
자식 클래스 입장에서는 부모 클래스의 기능을 전혀 사용하지 않지만 이 디자인 패턴을 위해
자식 클래스는 부모 클래스를 상속 받고 있다. 이는 부모 클래스 기능을 사용하든 안 하든 강하게 의존한다는 의미다.

0개의 댓글