Design pattern 5. Template Method Pattern

김미숙's avatar
Jul 22, 2025
Design pattern 5. Template Method Pattern
💡
가장 많이 쓰는 기술
핵심은 공통적인 기능을 추상화시키는 것

✅ 1. 템플릿 메서드 패턴이란?

  • 객체지향 디자인 패턴 중 하나로, 알고리즘의 전체 흐름은 상위 클래스에 정의하고, 세부 구현은 하위 클래스에 위임하는 패턴
  • 상위 클래스(추상 클래스)에 알고리즘의 공통적인 뼈대(템플릿)를 정의하고, 일부 단계는 하위 클래스가 구현하도록 만드는 패턴
 

🔧 구조

🔼 상위 클래스 (추상 클래스)
public abstract class LoginTemplate { // 템플릿 메서드 (고정된 로직 흐름) public final void loginProcess() { authenticate(); // 1단계 getProfile(); // 2단계 showMainPage(); // 3단계 } protected abstract void authenticate(); protected abstract Profile getProfile(); protected void showMainPage() { System.out.println("메인 페이지로 이동합니다."); } }
  • loginProcess()변하지 않는 알고리즘의 전체 흐름을 정의
  • authenticate()getProfile()하위 클래스가 구체적으로 구현
🔽 하위 클래스 (구체 구현)
public class GoogleLogin extends LoginTemplate { @Override protected void authenticate() { System.out.println("구글 로그인 인증 중..."); } @Override protected Profile getProfile() { System.out.println("구글 프로필 가져오기 완료"); return new GoogleProfile(1, "cos"); } }
public class KakaoLogin extends LoginTemplate { @Override protected void authenticate() { System.out.println("카카오 로그인 인증 중..."); } @Override protected Profile getProfile() { System.out.println("카카오 프로필 가져오기 완료"); return new KakaoProfile(2, "ssar"); } }
✅ 사용 예시
public class App { public static void main(String[] args) { LoginTemplate login = new GoogleLogin(); login.loginProcess(); // 고정된 흐름대로 실행 } }
출력:
구글 로그인 인증 중... 구글 프로필 가져오기 완료 메인 페이지로 이동합니다.
 

✅ 장점

장점
설명
✅ 코드 재사용
공통 로직은 상위 클래스에 작성, 반복 줄임
✅ 변경에 유연
세부 단계만 하위 클래스에서 오버라이드 가능
✅ 유지보수 용이
알고리즘 구조가 한 곳에 정의되어 명확함
 

❗️ 주의사항

  • 상속 기반이라 하위 클래스가 하나만 상속 가능
  • 너무 많은 추상 메서드를 강요하면 하위 클래스가 복잡해짐
 

💡 한줄 요약

템플릿 메서드는 전체 흐름은 상위 클래스에서 고정, 세부 로직만 하위 클래스에서 바꾸는 패턴
 

실습

HTMLTeacher
package ex05.teacher; public class HTMLTeacher { public void 수업시작() { 입장하기(); 출석부르기(); 강의하기(); 퇴장하기(); } private void 입장하기() { System.out.println("입장하기"); } private void 출석부르기() { System.out.println("출석부르기"); } private void 강의하기() { System.out.println("HTML 강의하기"); } private void 퇴장하기() { System.out.println("퇴장하기"); } }
JavaTeacher
package ex05.teacher; public class JavaTeacher { // 이 메서드만 노출되므로 개념상 interface - 강제성이 부여되어있음 public void 수업시작() { 입장하기(); 출석부르기(); 강의하기(); 퇴장하기(); } // public일 경우 자유도가 높아서 순서를 보장하기 힘들다 private void 입장하기() { System.out.println("입장하기"); } private void 출석부르기() { System.out.println("출석부르기"); } private void 강의하기() { System.out.println("Java 강의하기"); } private void 퇴장하기() { System.out.println("퇴장하기"); } }
PythonTeacher
package ex05.teacher; public class PythonTeacher { public void 수업시작() { 입장하기(); 출석부르기(); 강의하기(); 퇴장하기(); } private void 입장하기() { System.out.println("입장하기"); } private void 출석부르기() { System.out.println("출석부르기"); } private void 강의하기() { System.out.println("Python 강의하기"); } private void 퇴장하기() { System.out.println("퇴장하기"); } }
App
package ex05; import ex05.teacher.HTMLTeacher; import ex05.teacher.JavaTeacher; import ex05.teacher.PythonTeacher; public class App { public static void main(String[] args) { JavaTeacher jt = new JavaTeacher(); jt.수업시작(); PythonTeacher pt = new PythonTeacher(); pt.수업시작(); HTMLTeacher htt = new HTMLTeacher(); htt.수업시작(); } }
notion image
→ 공통적인 것들 중 강의하기는 구현체가 Teacher 마다 다 다르므로 추상메서드로 만들어야한다

추상화

  • 공통적인 것(Teacher)을 추상화 시킨다
Teacher
package ex05.teacher; public abstract class Teacher { public void 수업시작() { 입장하기(); 출석부르기(); 강의하기(); 퇴장하기(); } protected void 입장하기() { System.out.println("입장하기"); } protected void 출석부르기() { System.out.println("출석부르기"); } // 추상메서드 protected abstract void 강의하기(); protected void 퇴장하기() { System.out.println("퇴장하기"); } }
강의하기는 Teacher마다 다르므로 추상 메서드로 구현
수업시작을 제외하고는 노출되면 안 되므로 나머지 메서드는 protected로 구현 (캡슐화)
HTMLTeacher
package ex05.teacher; public class HTMLTeacher extends Teacher { @Override public void 강의하기() { System.out.println("HTML 강의하기"); } }
JavaTeacher
package ex05.teacher; public class JavaTeacher extends Teacher { @Override public void 강의하기() { System.out.println("Java 강의하기"); } }
PythonTeacher
package ex05.teacher; public class PythonTeacher extends Teacher { @Override public void 강의하기() { System.out.println("Python 강의하기"); } }
App
package ex05; import ex05.teacher.HTMLTeacher; import ex05.teacher.JavaTeacher; import ex05.teacher.PythonTeacher; import ex05.teacher.Teacher; public class App { public static void main(String[] args) { Teacher jt = new JavaTeacher(); jt.수업시작(); Teacher pt = new PythonTeacher(); pt.수업시작(); Teacher htt = new HTMLTeacher(); htt.수업시작(); } }

인터페이스 만들기

  • 인터페이스를 정의하는 목적: 노출시키고 싶은 것만 노출하기 위함
TeacherAble
package ex05.teacher; /* 주석으로 누가 만들었는지, 어디서 구현하면 되는지 기재 */ public interface TeacherAble { // 이 메서드만 노출시킨다 void 수업시작(); }
Teacher
package ex05.teacher; public abstract class Teacher implements TeacherAble { public void 수업시작() { 입장하기(); 출석부르기(); 강의하기(); 퇴장하기(); } protected void 입장하기() { System.out.println("입장하기"); } protected void 출석부르기() { System.out.println("출석부르기"); } // 추상메서드 protected abstract void 강의하기(); protected void 퇴장하기() { System.out.println("퇴장하기"); } }
notion image
Share article

parangdajavous