본문 바로가기
Design Pattern

[Design Pattern] 탬플릿 메서드 패턴

by 진꿈청 2024. 3. 28.

이번 포스팅에서는 디자인 패턴 중 하나인 템플릿 메서드 패턴에 관해 알아본다.

 

 

우선, 템플릿 메서드 패턴을 알아보기 위해 App, Teacher 클래스를 생성한다.

 

Teacher

public class Teacher {
    private void 입장하기(){
        System.out.println("입장하기");
    }

    private void 출석부르기(){
        System.out.println("출석부르기");
    }


    private void 퇴장하기(){
        System.out.println("퇴장하기");
    }

    public void 수업시작(){
        입장하기();
        출석부르기();
        퇴장하기();
    }
}

 

App.java

public class App {
    public static void main(String[] args) {
        Teacher teacher = new JavaTeacher();
        teacher.수업시작();
    }
}

 

Teacher는 수업시작시

(수업시작 - 내부가 어떻게 구성되어있는지 모르지만 수업시작()만 호출하면 되므로 캡슐화라고 볼 수 있다.)

입장하기 -> 출석부르기 -> 퇴장하기의 역할을 한다.

 

이때, JavaTeacher와 PythonTeacher를 추가해보자.

 

JavaTeacher

public class JavaTeacher {
    private void 입장하기(){
        System.out.println("입장하기");
    }

    private void 출석부르기(){
        System.out.println("출석부르기");
    }

    private void 강의하기(){
        System.out.println("Java 강의하기");
    }
    private void 퇴장하기(){
        System.out.println("퇴장하기");
    }

    public void 수업시작(){
        입장하기();
        출석부르기();
        강의하기();
        퇴장하기();
    }
}

 

 

PythonTeacher

public class PythonTeacher {
    private void 입장하기(){
        System.out.println("입장하기");
    }

    private void 출석부르기(){
        System.out.println("출석부르기");
    }

    private void 강의하기(){
        System.out.println("Python 강의하기");
    }
    private void 퇴장하기(){
        System.out.println("퇴장하기");
    }

    public void 수업시작(){
        입장하기();
        출석부르기();
        강의하기();
        퇴장하기();
    }
}

 

 

App

public class App {
    public static void main(String[] args) {
        JavaTeacher javaTeacher = new JavaTeacher();
        javaTeacher.수업시작();

        PythonTeacher pythonTeacher = new PythonTeacher();
        pythonTeacher.수업시작();
    }
}

 

이런식으로 구성이 될 것이다.

하지만, JavaTeacher와 PythonTeacher, Teacher 클래스들은 중복된 코드가 존재한다. 

 

 

그래서, 이 중복된 코드를 줄이기 위해 Teacher에 강의하기 메소드를 선언하여

자식들이 강의하기에 관해 각각 구현하게끔 미루는 작업을 수행한다.

 

public abstract class Teacher {
    private void 입장하기(){
        System.out.println("입장하기");
    }

    private void 출석부르기(){
        System.out.println("출석부르기");
    }

    abstract void 강의하기();

    private void 퇴장하기(){
        System.out.println("퇴장하기");
    }

    public void 수업시작(){
        입장하기();
        출석부르기();
        강의하기();
        퇴장하기();
    }
}

즉, 강의하기와 같이 정의되지 않은 것들을 자식에게 미루고 나머지 메서드는 탬플릿으로 사용한다.

 

 

저렇게 Teacher를 추상 클래스로 등록하면 JavaTeacher와 PythonTeacher는 아래와 같이 변경이 가능하다.

 

JavaTeacher

public class JavaTeacher extends Teacher{
    
    // 재정의
    void 강의하기(){
        System.out.println("Java 강의하기");
    }
}

 

PythonTeacher

public class PythonTeacher extends Teacher{

    // 재정의
    void 강의하기(){
        System.out.println("Python 강의하기");
    }

}

 

중복된 코드가 사라진 것을 알 수 있다.

 

근데 여기서 중요한 점이 있다.

 

JavaTeacher, PythonTeacher에서 강의하기를 재정의한 것은 오버라이드와는 조금 다르다.

 

오버라이드는 "무효화" 라는 것으로 오버라이드(부모의 메서드를 무효화하다.)  재정의와는 조금 다르다.

abstract void 강의하기();

 

즉, 자식 클래스가 강의하기를 재정의하면 실행시 자동으로 오버라이드 되고
Teacher의 자식인 JavaTeacher의 강의하기 메서드가 실행된다.


이걸 강의하기 메서드가 동적 바인딩된 것이라고 한다.

 

그래서 App 클래스도 다음과 같이 수정할 수 있다.

 

App

public class App {
    public static void start(Teacher t){
        t.수업시작();
    }

    public static void main(String[] args) {
        JavaTeacher javaTeacher = new JavaTeacher();
        start(javaTeacher);

        PythonTeacher pythonTeacher = new PythonTeacher();
        start(pythonTeacher);
    }
}

 

훨씬 객체지향적 설계가 되었다.

 

 

여기까지 탬플릿 메서드 패턴에 관해 알아보았다.

 

 

 

 

 

 

'Design Pattern' 카테고리의 다른 글

[Design Pattern] 팩토리 패턴  (0) 2024.04.04
[Design Pattern] 데코레이터 패턴  (0) 2024.04.01
[Design Pattern] 싱글톤 패턴  (0) 2024.03.25
[Design Pattern] 어댑터 패턴  (0) 2024.03.18
[Design Pattern] 프록시 패턴  (1) 2024.03.12