상위 클래스쪽에 템플릿에 해당하는 메소드가 정의되어 있고, 그 메소드의 정의 안에는 추상 메소두가 사용되고 있다. 따라서 상위 클래스의 프로그램만 보면 추상 메소드를 어떻게 호출하고 있는지 알 수 있지만, 최정적으로 어떤 처리가 수행되는지는 알 수 없다.
추상 메소드를 실제로 구현하는 것은 하위 클래스이며 서로 다른 하위 클래스가 서로 다른 구현을 실행하면 서로 다른 처리가 실행 될 것이다. 그러나 어떤 하위 클래스에서 어떤 구현을 하더라도 처리의 큰 흐름은 상위 클래스에서 결정한대로 이루어진다.
이와같이 상위 클래스에서 처리의 뼈대를 결정하고, 하위 클래스에서 그 구체적인 내용을 결정하는 디자인 패턴을 Template Method pattern 이라고 한다.
예제 프로그램) 문자나 문자열을 5회 반복해서 표시하기
public abstract class AbstractDisplay { public abstract void open(); public abstract void print(); public abstract void close(); public final void display() { open(); for(int i=0; i<5; i++) { print(); } close(); } } |
public class CharDisplay extends AbstractDisplay { private char ch; public CharDisplay(char ch) { this.ch = ch; } public void open() { System.out.println("<<"); } public void print() { System.out.println(ch); } public void close() { System.out.println(">>"); } } |
public class StringDisplay extends AbstractDisplay { private String str; private int width; public StringDisplay(String str) { this.str = str; this.width = str.getBytes().length; } public void open() { printLine(); } public void print() { System.out.println("|" + str + "|"); } public void close() { printLine(); } private viod printLine() { System.out.print("+"); for(int i=0; i<width; i++) { System.out.print("-"); } System.out.println("+"); } } |
public class Main { public static void main(String[] args) { AbstractDisplay d1 = new CharDisplay('H'); AbstractDisplay d2 = new StringDisplay("hello world"); d1.display(); d2.display(); } } |
Template Method pattern의 등장인물
- Abstract class(추상 클래스)의 역할 (템플릿 메소드를 구현.)
- Concrete class (구현 클래스)의 역할 (추상 메소드를 구체적으로 구현)
Template Method pattern의 이점(로직을 공통화 할 수 있다.)
하위 클래스를 상위 클래스와 동일시 한다.
위의 예제를 보면 CharDisplay의 인스턴스도, StringDisplay의 인스턴스도 AbstractDisplay형의 변수에 대입하고 있다.
그리고 display 메소드를 호출하고 있다. 상위 클래스형의 변수가 있고, 그 변수에 하위 클래스형의 인스턴스가 대입된다고 가정해보면,
이때 instanceof등으로 하위 클래스의 종류를 특정하지 않아도 프로그램이 작동하도록 만드는 것이 좋다.
"상위 클래스형의 변수에 항위 클래스의 어떠한 인스턴스를 대입해도 제대로 작동할 수 있도록 한다." 는 원칙은
The Liskov Substitution Principle(LSP)이라고 불린다.
이 LSP는 Template Method 패턴에 국한되지 않는 상속의 일반적인 원칙이다.
어떤 처리를 상위 클래스에 두고 어떤 처리를 하위 클래스에 둘 것인지를 정한 메뉴얼은 없다. 이건 프로그램을 설계하는 사람의 몫이다.
관련 패턴
Factory Method pattern, Strategy pattern