템플릿 메서드 패턴

박윤택·2023년 8월 29일
0

디자인 패턴

목록 보기
1/2

템플릿 메서드 패턴

공통된 부분이 있고 다른 부분이 있을때 abstract class로 정의하고 다른 부분을 abstract method로 정의하여 이를 상속 받아 따로 정의하여 사용하는 패턴이다. 즉 변경하는 부분과 변경하지 않는 부분을 분리할 수 있다.
쉽게 생각해서 템플릿을 만들어서 이를 사용하는 패턴이라고 보면 된다.
이를 이용하면 하위 클래스가 구조를 변경하지 않고도 로직을 재정의할 수 있다.

자식 클래스와 부모 클래스가 컴파일 시점에 강력하게 결합되는 문제가 있다. 자식 클래스에서는 부모 클래스의 기능을 전혀 사용하지 않는 경우가 있고 부모 클래스의 모든 기능들을 상속 받고 있다. 즉, 부모 클래스에 의존하고 있다.

템플릿 메서드 패턴과 비슷하지만 상속의 단점을 개선하기 위해 위임을 이용하는 전략패턴을 이용할 수 있다.

방법

  1. abstract class 를 정의하고 이를 상속 받아 abstract method를 구현한다.
  2. 익명 내부 클래스를 이용한다.

예시 - 1 (abstract class 상속)

@Sl4j
abstract class AbstractTemplate {
	void execute() {
    	long startTime = System.currentTimeMillis();
        call();
        long endTime = System.currentTimeMillis();
        long resultTime = endTime - startTime;
        log.info("resultTime={}", resultTime);
    }
    
    abstract void call();
}

@Sl4j
class SubClass1 extends AbstractTemplate {
	@Override
    void call() {
    	log.info("로직1 실행");
    }
}

@Sl4j
class SubClass2 extends AbstractTemplate {
	@Override
    void call() {
    	log.info("로직2 실행");
    }
}

public class Main {
	public static void main(String args[]) {
    	AbstractTemplate template1 = new SubClass1();
        template1.execute(); // 로직 1 실행 출력
        
        AbstractTemplate template2 = new SubClass2();
        template2.execute(); // 로직 2 실행 출력
    }

}

예시 - 2 (익명 내부 클래스 이용)

@Sl4j
abstract class AbstractTemplate {
	void execute() {
    	long startTime = System.currentTimeMillis();
        call();
        long endTime = System.currentTimeMillis();
        long resultTime = endTime - startTime;
        log.info("resultTime={}", resultTime);
    }
    
    abstract void call();
}

public class Main {
	public static void main(String[] args) {
    	AbstractTemplate template1 = new AbstractTemplate() {
        	@Override
            void call() {
            	log.info("로직 1 실행");
            }
        }
        
        AbstractTemplate template2 = new AbstractTemplate() {
        	@Override
            void call() {
            	log.info("로직 2 실행");
            }
        }
        
        template1.execute(); // 로직 1 실행 출력
        template2.execute(); // 로직 2 실행 출력
    }
}

방법 1 과 방법 2 의 차이는 방법 1을 이용할 경우 클래스를 계속해서 생성해야 하는 단점이 있다. 그리고 익명 내부 클래스를 getClass()로 확인해 보면 java가 임의로 크래스 이름을 임의로 만들어줘서 Main$1, Main$2로 확인이 된다.

단일 책임 원칙

템플릿 메서드 패턴을 적용하여 변경이 일어나는 부분과 변경이 일어나지 않는 부분을 분리하여 단일 책임 원칙을 준수하게 된다.

0개의 댓글