Computer Science/디자인 패턴

Template Method Pattern (템플릿 메소드 패턴)

조용우 2025. 4. 22. 17:18

템플릿 메서드는 부모 클래스에서 알고리즘의 골격을 정의하지만, 해당 알고리즘의 구조를 변경하지 않고 자식 클래스들이 알고리즘의 특정 단계들을 오버라이드​(재정의)​할 수 있도록 하는 행동 디자인 패턴입니다.

여러 코드에서 중복되는 부분이 존재할 때, 그 중 중복되지 않는 부분만 재정의 할 수 있도록 따로 빼는 것 

 

Ex)

DocDataMiner, CSVDataMiner, PDFDataMiner의 mine 메소드에서,

rawData = extract(Doc/CSV/PDF)Data(file) 

data = parse(Doc/CSV/PDF)Data(rawdata)

부분을 제외하면 모두 같음.

 

변하는 부분과, 변하지 않는 부분을 분리하여 모듈화 할 수 있으면 더 깔끔한 구조가 될 것.

 


템플릿 메서드 패턴은, "템플릿" 이라는 기준이 되는 거대한 틀에서 변하지 않는 부분을 정의하고, 변하는 부분은 별도로 호출해서 해결하는 방식.

 

템플릿이 되는 베이스를 추상 클래스로 구현

public abstract class AbstractTemplate {

	public void 변하지_않는_부분() {
    	System.out.println("변하지 않는 부분 시작");
        변하는_부분(); // 상속
        System.out.println("변하지 않는 부분 종료");
    }
    
    protected abstract void 변하는_부분();
}

 

바뀌는 부분은 추상 클래스를 상속받아 사용

public class Template1 extends AbstractTemplate {
	
    @Override
    protected void 변하는_부분() {
    	System.out.println("변하는 부분 - Template 1");
    }
}


public class Template2 extends AbstractTemplate {
	
    @Override
    protected void 변하는_부분() {
    	System.out.println("변하는 부분 - Template 2");
    }
}

 

실 사용 예제

public class TemplateMethodPattern {
	
    void test() {
    	AbstractTemplate template1 = new Template1():
        template1.변하지_않는_부분();
        
        AbstractTemplate template2 = new Template2():
        template2.변하지_않는_부분();
    }
}

// 결과

// 변하지 않는 부분 시작
// 변하는 부분 - Template 1
// 변하지 않는 부분 종료

// 변하지 않는 부분 시작
// 변하는 부분 - Template 2
// 변하지 않는 부분 종료

 

 

단점:

변하는 부분이 늘어날 때 마다, Template1, Template2, ... Template100 ... 클래스를 계속해서 만들어야 함. 이 단점은 익명 내부 클래스를 이용하여 보완 가능

 

바뀌는 부분은 추상 클래스를 상속받아 상속하는 것이 아닌, 실 사용 부분에서 직접 정의하는 것.

public class TemplateMethodPattern {
	
    void test() {
    	AbstractTemplate template1 = new AbstractTemplate() {
            @Override
            protected void 변하는_부분() {
            	System.out.println("변하는 부분 - Template 1")
            }
        }
        template1.변하지_않는_부분();
        
        AbstractTemplate template2 = new AbstractTemplate() {
            @Override
            protected void 변하는_부분() {
            	System.out.println("변하는 부분 - Template 2")
            }
        }
        template2.변하지_않는_부분();
    }
}

// 결과

// 변하지 않는 부분 시작
// 변하는 부분 - Template 1
// 변하지 않는 부분 종료

// 변하지 않는 부분 시작
// 변하는 부분 - Template 2
// 변하지 않는 부분 종료

 

여기서, template1와 template2의 Class는 해당 클래스가 선언된 클래스$1 와 같은 이름이 됨

System.out.println(template1.getClass());
System.out.println(template1.getClass());

// 결과
// class packagename.packagename.TemplateMethodPattern$1
// class packagename.packagename.TemplateMethodPattern$2

 

장점:

템플릿 메소드 패턴을 적용하지 않은 경우 위 DocDataMiner, CSVDataMiner, PDFDataMiner의 예제에서 코드에 변경이 일어날 때, 3개의 클래스를 모두 변경해줘야 함. 이 클래스가 100개 있었다면 100개를 변경해줘야 함.

 

하지만, 템플릿 메소드 패턴을 통해 변하지 않는 부분에 단일 책임 원칙을 지키며 변경 지점을 하나로 모아 변경에 쉽게 대처할 수 있는 구조가 되었음. ex) 변하지 않는 부분을 수정할 때, 100번 고칠걸 이제는 1번만 고치면 된다.

 

 

하지만

템플릿 메소드 패턴은 상속을 이용하기 때문에 상속의 단점들이 존재한다.

 

자식 클래스는 부모 클래스의 기능을 사용하지 않지만, 컴파일 시점부터 부모 클래스를 알아야 하고, 의존해야 한다. 이에 따라 부모 클래스가 변경될 경우 자식 클래스에도 영향을 주게 된다.

 

이러한 단점을 제거할 수 있는, 템플릿 메소드 패턴과 유사한 디자인 패턴이 전략 패턴이다. 

 

 

Reference

스프링 핵심 원리 - 고급편

https://refactoring.guru/ko/design-patterns/template-method

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

Strategy Pattern (전략 패턴)  (1) 2025.04.22