1. 템플릿 메서드 패턴 (Template Method Pattern)
1️⃣ 템플릿 메서드 패턴이란?
1) 개념
- 알고리즘의 뼈대는 고정하고, 일부 단계만 바꿀 수 있게 하는 패턴
전체 작업 흐름은 부모 클래스가 정해두고, 세부 동작은 자식 클래스가 결정하는 구조
2️⃣ 비유로 이해하기
1) 요리 레시피
- 라면 끓이기 과정
1️⃣ 물 끓이기
2️⃣ 면 넣기
3️⃣ 스프 넣기
4️⃣ 마무리
- 스프 종류는 다를 수 있음
- 토핑은 다를 수 있음
- 전체 순서는 고정, 세부 내용만 변경
➡️ 이게 템플릿 메서드 패턴
3️⃣ 템플릿 메서드 패턴이 필요한 이유
- 비슷한 작업들 존재
- 전체 과정은 거의 동일
- 일부 단계만 다름
➡️ 매번 코드를 복붙하면 유지보수 지옥 😱
⬇️
- 공통 흐름은 한 번만 작성
- 다른 부분만 교체 가능
4️⃣ 핵심 특징 ⭐
- 알고리즘 구조 고정
- 세부 구현 유연
- 코드 재사용 극대화
- 변경 영향 최소화
5️⃣ 템플릿 메서드 패턴의 장단점
1) 장점 👍
- 코드 중복 제거
- 유지보수 쉬움
- 구조 안정적
- 확장 용이
2) 단점 👎
- 클래스 수 증가
- 설계 이해 필요
- 과도하게 쓰면 복잡
6️⃣ 언제 쓰면 좋을까?
- 작업 순서는 동일한데
- 일부 단계만 달라질 때
- 예
- 파일 처리 (CSV / Excel / JSON)
- 게임 캐릭터 행동 로직
- 로그인 절차 (SNS / 이메일 등)
7️⃣ 구성 요소
1) 부모 클래스 – 작업 순서 정의
- 역할
- 알고리즘의 뼈대 제공
public abstract class Parent {
// ✅ 템플릿 메서드 (작업 순서 고정)
public final void process() {
stepA();
stepB(); // 자식이 변경 가능
stepC();
stepD();
}
protected void stepA() {
System.out.println("Step A 실행");
}
// ✅ 자식에게 위임
protected abstract void stepB();
protected void stepC() {
System.out.println("Step C 실행");
}
protected void stepD() {
System.out.println("Step D 실행");
}
}💡 핵심 포인트 💡
abstract class→ 직접 생성 불가
final process()→ 순서 변경 방지 🚫
abstract stepB()→ 변경 지점
2) 자식 클래스 – 특정 단계만 변경
- 역할
- 일부 단계만 구현
public class Child extends Parent {
@Override
protected void stepB() {
System.out.println("Step B 특별 처리 ✨");
}
}3) 실행 코드
public class Main {
public static void main(String[] args) {
Parent obj = new Child();
obj.process();
}
}🖥 실행 결과
Step A 실행
Step B 특별 처리 ✨
Step C 실행
Step D 실행➡️ 전체 흐름은 부모가 제어
➡️ 변경은 특정 단계만
8️⃣ 코드 예시
1) 부모 클래스 (Template)
public abstract class DataProcessor {
// ✅ 템플릿 메서드 (알고리즘 뼈대)
public final void process() {
readData();
processData(); // 변경 가능한 부분
saveData();
}
// ✅ 공통 로직
private void readData() {
System.out.println("데이터를 읽습니다.");
}
// ✅ 자식이 구현해야 하는 부분
protected abstract void processData();
// ✅ 공통 로직
private void saveData() {
System.out.println("데이터를 저장합니다.");
}
}💡 핵심 포인트
abstract class→ 객체 직접 생성 불가
final process()→ 순서 변경 방지 🚫
abstract method→ 자식에게 위임
2) 자식 클래스 – Excel 처리
public class ExcelProcessor extends DataProcessor {
@Override
protected void processData() {
System.out.println("Excel 데이터 가공 중...");
}
}3) 자식 클래스 – CSV 처리
public class CsvProcessor extends DataProcessor {
@Override
protected void processData() {
System.out.println("CSV 데이터 가공 중...");
}
}4) 실행 코드 (Client)
public class Main {
public static void main(String[] args) {
DataProcessor excel = new ExcelProcessor();
excel.process();
System.out.println("----------------");
DataProcessor csv = new CsvProcessor();
csv.process();
}
}🖥 실행 결과
데이터를 읽습니다.
Excel 데이터 가공 중...
데이터를 저장합니다.
----------------
데이터를 읽습니다.
CSV 데이터 가공 중...
데이터를 저장합니다.➡️ 흐름은 동일, 세부 동작만 다름
9️⃣ 다른 패턴과 차이
패턴 | 차이점 |
전략 패턴 | 알고리즘 자체 교체 |
템플릿 메서드 | 알고리즘 구조는 고정 |
➡️ 전략 = 전체 교체
➡️ 템플릿 = 일부 교체
🔟 그림으로 이해하기

2. 실습 (ex05)
1️⃣ 기본
1) Teacher.java
C:\workspace\java_lab\designapp\src\ex05\teacher\TeacherTemplate.java
package ex05;
import ex05.teacher.Teacher;
public class App {
public static void main(String[] args) {
Teacher tt = new Teacher();
tt.입장하기();
tt.출석부르기();
tt.강의하기();
tt.퇴장하기();
}
}2) App.java
C:\workspace\java_lab\designapp\src\ex05\App.java
package ex05;
import ex05.teacher.TeacherTemplate;
public class App {
public static void main(String[] args) {
TeacherTemplate tt = new TeacherTemplate();
tt.입장하기();
tt.출석부르기();
tt.강의하기();
tt.퇴장하기();
}
}3) 결과

2️⃣ 강의하기() 메서드만 다르게
1) Teacher.java
C:\workspace\java_lab\designapp\src\ex05\teacher\Teacher.java
package ex05.teacher;
public abstract class Teacher {
public void 입장하기() {
System.out.println("입장하기");
}
public void 출석부르기() {
System.out.println("출석부르기");
}
// 구현체에게 구체적인 행위를 미루기
public abstract void 강의하기();
public void 퇴장하기() {
System.out.println("퇴장하기");
}
}2) HtmlTeacher.java
C:\workspace\java_lab\designapp\src\ex05\teacher\HtmlTeacher.java
package ex05.teacher;
public class HtmlTeacher extends Teacher {
@Override
public void 강의하기() {
System.out.println("html 강의하기");
}
}3) App.java
C:\workspace\java_lab\designapp\src\ex05\App.java
package ex05;
import ex05.teacher.HtmlTeacher;
import ex05.teacher.Teacher;
public class App {
public static void main(String[] args) {
Teacher tt = new HtmlTeacher();
tt.입장하기();
tt.출석부르기();
tt.강의하기();
tt.퇴장하기();
}
}4) 결과

3️⃣ PythonTeacher 클래스 추가
1) PythonTeacher.java
C:\workspace\java_lab\designapp\src\ex05\teacher\PythonTeacher.java
package ex05.teacher;
public class PythonTeacher extends Teacher{
@Override
public void 강의하기() {
System.out.println("Python 강의하기");
}
}2) App.java
C:\workspace\java_lab\designapp\src\ex05\App.java
package ex05;
import ex05.teacher.HtmlTeacher;
import ex05.teacher.PythonTeacher;
import ex05.teacher.Teacher;
public class App {
public static void main(String[] args) {
Teacher tt = new PythonTeacher();
tt.입장하기();
tt.출석부르기();
tt.강의하기();
tt.퇴장하기();
}
}3) 결과

4️⃣ 수업하기() 메서드 만들기
1) Teacher.java
C:\workspace\java_lab\designapp\src\ex05\teacher\Teacher.java
package ex05.teacher;
public abstract class Teacher {
// 순서 보장
public void 수업하기() {
입장하기();
출석부르기();
강의하기();
퇴장하기();
}
private void 입장하기() {
System.out.println("입장하기");
}
private void 출석부르기() {
System.out.println("출석부르기");
}
// 구현체에게 구체적인 행위를 미루기
protected abstract void 강의하기();
// private하면 자식이 상속을 못하기 때문에 protected!
private void 퇴장하기() {
System.out.println("퇴장하기");
}
}순서를 실수할 수 있기 때문에
수업하기() 메서드로 순서 보장해주고, 그 안의 메서드 접근 못하도록 private으로 접근 제한2) App.java
C:\workspace\java_lab\designapp\src\ex05\App.java
package ex05;
import ex05.teacher.HtmlTeacher;
import ex05.teacher.PythonTeacher;
import ex05.teacher.Teacher;
public class App {
public static void main(String[] args) {
Teacher tt = new PythonTeacher();
tt.수업하기();
}
}3) JavaTeacher.java
C:\workspace\java_lab\designapp\src\ex05\teacher\JavaTeacher.java
package ex05.teacher;
public class JavaTeacher extends Teacher{
@Override
protected void 강의하기() {
System.out.println("JAVA 강의하기");
}
}4) App.java
C:\workspace\java_lab\designapp\src\ex05\App.java
package ex05;
import ex05.teacher.JavaTeacher;
import ex05.teacher.Teacher;
public class App {
public static void main(String[] args) {
Teacher tt = new JavaTeacher();
tt.수업하기();
}
}5) 결과

Share article