[DesignPattern] 템플릿 메서드 패턴

템플릿 메서드 패턴


Templete Method 패턴은 템플릿의 기능을 가진 패턴이다. 상위 클래스 쪽에 템플릿에 해당하는 메서드가 정의되어 있고, 그 메서드의 정의 안에는 추상 메서드가 사용되고 있다.

따라서 상위 클래스의 프로그램만 보면 추상 메서드를 어떻게 호출하고 있는지 알 수 있지만, 최종적으로 어떤 처리가 수행되는지는 알 수 없다.

추상 메서드를 실제로 구현하는 것은 하위 클래스이다. 하위 클래스 측에서 메서드를 구현하면 구체적인 처리가 결정된다. 서로 다른 하위 클래스가 서로 다른 구현을 실행하면 서로 다른 처리가 결정된다. 서로 다른 하위 클래스가 서로 다른 구현을 실행하면 서로 다른 처리가 실행될 것이다.

그러나 어떤 하위 클래스에서 어떤 구현을 하더라도 처리의 큰 흐름은 상위 클래스에서 결정한대로 이루어진다. 이와 같이 상위 클래스에서 처리의 뼈대를 결정하고, 하위 클래스에서 그 구체적인 내용을 결정하는 디자인 패턴을 템플릿 메서드 패턴이라고 한다.




▶ 등장인물

 이름

 해설

 AbstractDisplay

 메서드 display만 구현되고 있는 추상 클래스

 CharDisplay

 메서드 open, print, close를 구현하고 있는 클래스

 StringDisplay

 메서드 open, print, close를 구현하고 있는 클래스

 Main

 동작 테스트용 클래스


1. AbstractDisplay 

- AbstractClass(추상 클래스)의 역할AbstractClass는 템플릿 메서드를 구현한다. 또한 그 템플릿 메서드에서 사용하고 있는 추상 메서드를 선언한다. 이 추상 메서드를 선언한다.

이 추상 메서드는 하위 클래스인 ConcreateClass 역할에 의해 구현된다.

public abstract class AbstractDisplay { // 추상 클래스 AbstractDisplay

  public abstract void open(); // 하위 클래스에 구현을 맡기는 추상 메소드 (1) open

    public abstract void print(); // 하위 클래스에 구현을 맡기는 추상 메소드 (2) print

    public abstract void close(); // 하위 클래스에 구현을 맡기는 추상 메소드 (3) close

    public final void display() { // 추상 클래스에서 구현되고 있는 메소드 display

        open(); // 우선 open하고…

        for (int i = 0; i < 5; i++) { // 5번 print을 반복하고…

            print();                    

        }

        close(); // … 마지막으로 close한다. 이것이 display 메소드에서 구현되고 있는 내용.

    }

}


2. CharDisplay 

- ConcreateClass(구현 클래스)의 역할AbstractClass 역할에서 정의되어 있는 추상 메서드를 구체적으로 구현한다. 여기에서 구현한 메서드는 AbstractClass역의 템플릿 메서드에서 호출된다. 예제 프로그램에서는 CharDisplay 클래스나 StringClass 클래스가 이 역할을 한다.

public class CharDisplay extends AbstractDisplay {  // CharDisplay는 AbstractDisplay의 하위 클래스.

   private char ch;  // 표시해야 할 문자

   public CharDisplay(char ch) { // 생성자에서 전달된 문자 ch을

       this.ch = ch; // 필드에 기억해 둔다.

   }

   public void open() { // 상위 클래스에서는 추상 메소드였다. 여기에서 오버라이드해서 구현.

       System.out.print("<<");                   

   }

   public void print() { // print 메소드도 여기에서 구현한다. 이것이 display에서 반복해서 호출된다.

       System.out.print(ch); // 필드에 기억해 둔 문자를 1개 표시한다.

   }

   public void close() { // close 메소드도 여기에서 구현.

       System.out.println(">>");                  

   }

}


3. StringDisplay 

public class StringDisplay extends AbstractDisplay {  // StringDisplay도 AbstrctDisplay의 하위 클래스.

    private String string;  // 표시해야 할 문자열.

    private int width; // 바이트 단위로 계산한 문자열의 「폭」.

    public StringDisplay(String string) { // 생성자에서 전달된 문자열 string을

        this.string = string; // 필드에 기억.

        this.width = string.getBytes().length; // 그리고 바이트 단위의 폭도 필드에 기억해 두고 나중에 사용한다.

    }

    public void open() { // 오버라이드해서 정의한 open 메소드.

        printLine(); // 이 클래스의 메소드 printLine에서 선을 그리고 있다.

    }

    public void print() { // print 메소드는

        System.out.println("|" + string + "|"); // 필드에 기억해 둔 문자열의 전후에 “|”을 붙여서 표시.

    }

    public void close() { // close 메소드는

        printLine(); // open 처럼 printLine 메소드에서 선을 그리고 있다.

    }

    private void printLine() { // open과 close에서 호출된 printLine 메소드이다. private이기 때문에 이 클래스 안에서만 사용된다.

        System.out.print("+"); // 테두리의 모서리를 표현하는”+” 마크를 표시.

        for (int i = 0; i < width; i++) { // width개의 “-“을 표시하고

            System.out.print("-"); // 테두리 선으로 이용한다.

        }

        System.out.println("+"); // 테두리의 모서리를 표현하는 “+” 마크를 표시.

    }

}


4. Main 

public class Main {

    public static void main(String[] args) {

        AbstractDisplay d1 = new CharDisplay('H'); // 'H'을 가진 CharDisplay 인스턴스를 1개 만든다.

        AbstractDisplay d2 = new StringDisplay("Hello, world."); // “Hello, world.”을 가진 StringDisplay의 인스턴스를 1개 만든다.

        AbstractDisplay d3 = new StringDisplay("안녕하세요."); // “안녕하세요.”를 가진 StringDisplay의 인스턴스를 1개 만든다.

        d1.display(); // d1, d2, d3 모두 AbstractDisplay의 하위클래스의 인스턴스이기 때문에

        d2.display(); // 상속한 display메소드를 호출할 수 있다.

        d3.display(); // 실제 동작은 CharDisplay나 StringDisplay에서 결정한다.

    }

}


실행결과)

<<HHHHH>>

+-------------+

|Hello, world.|

|Hello, world.|

|Hello, world.|

|Hello, world.|

|Hello, world.|

+-------------+

+----------------+

|안녕하세요.|

|안녕하세요.|

|안녕하세요.|

|안녕하세요.|

|안녕하세요.|

+----------------+