템플릿 메소드 패턴은 부모-자식 계층구조를 갖는 프로그램에서 부모 클래스에서 템플릿 메소드라는 특이한 형태로 구현한 메소드를 이용하는 방식으로 추상메소드를 통해서 부모에서 정의한 함수들을 자식클래스에서 구현하지만
이 템플릿 메소드만큼은 부모클래스에서 구현한다. 이 템플릿 메소드는 해당 클래스 내부에 존재하는 추상메소드를 호출하는 형태로 구현되어 있는것이 특징이다.(부모 클래스의 객체 생성만으로는 사용이 불가능)
부모-자식의 계층구조를 가지면서 프로그램내 흐름을 지정하고자 할때 사용한다.
앞서 설명했듯 상위 클래스에서 어떤 처리흐름에 대한 골격을 정하고, 구체적인 처리의 내용은 하위클래스에서결정하기 위해서 사용한다.
사실 구조는 단순하다,상위 클래스에서 템플릿이 될 메소드만 제외하고 나머지를 하위에서 구현하도록 설계하면 된다.
Abstract Class
상위클래스를 의미하며, 여기서 템플릿 메소드를 구현한다.
나머지 메소드는 추상메소드로 만들어서 하위 클래스인 Concreate Class에서 구현하도록 만들어 준다.
Concreate Class
Abstract Class를 상속받아 추상메소드를 구현하는 클래스로 여기서 구현하는 추상메소드는 Abstract Class의 템플릿 메소드에서 호출된다.
다음 형태를 따르는 코드를 작성해 보겠다.
public abstract class AbstractDisplay {
public abstract void open();
public abstract void print();
public abstract void close();
public final void display() {
open(); //this.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;
}
@Override
public void open() {
System.out.print("<<");
}
@Override
public void print() {
System.out.print(ch);
}
@Override
public void close() {
System.out.println(">>");
}
}
public class StringDisplay extends AbstractDisplay {
private String string;
private int width;
public StringDisplay(String string) {
this.string = string;
this.width = string.length;
}
@Override
public void open() {
printLine();
}
@Override
public void print() {
System.out.println("|" + string + "|");
}
@Override
public void close() {
printLine();
}
private void 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();
}
}
출력결과
import Foundation
// AbstractDisplay 프로토콜 정의
protocol AbstractDisplay {
func open()
func printContent()
func close()
}
// 프로토콜 확장을 통해 기본 구현 제공
extension AbstractDisplay {
func display() {
open()
for _ in 0..<5 {
printContent()
}
close()
}
}
// CharDisplay 클래스 정의
class CharDisplay: AbstractDisplay {
private var ch: Character
init(ch: Character) {
self.ch = ch
}
func open() {
print("<<", terminator: "")
}
func printContent() {
print(ch, terminator: "")
}
func close() {
print(">>")
}
}
// StringDisplay 클래스 정의
class StringDisplay: AbstractDisplay {
private var string: String
private var width: Int
init(string: String) {
self.string = string
self.width = string.count
}
func open() {
printLine()
}
func printContent() {
print("|" + string + "|")
}
func close() {
printLine()
}
private func printLine() {
print("+", terminator: "")
for _ in 0..<width {
print("-", terminator: "")
}
print("+")
}
}
// 사용 예시
let d1: AbstractDisplay = CharDisplay(ch: "H")
let d2: AbstractDisplay = StringDisplay(string: "Hello, world.")
d1.display()
d2.display()
Swift에는 추상클래스를 제공하지 않고,
프로토콜에서 바로 함수를 기본정의 하는것을 허용하지 않으니 템플릿 메소드는 프로토콜을 extension해서 구현하였다.
템플릿 메소드 패턴은 코드 처리 구조를 상위 단계에서 구현하고 나머지 상세부분은 하위 클래스에서 구현하도록 설계하는 디자인 패턴이다.