어떤 기능에 대해서 실행 되어야 할 각 단계에 대한 순서만을 일단 정해두고, 각 단계에 대한 세부 구현을 상황에 따라 다르게 구현할 수 있도록 하는 패턴이다.
예시로 패턴을 이해해 보자.
NoteTemplate
: 아직 구현되지 않는 각 단계를 정해진 순서대로 실행해주는 클래스이다. 즉, 이 클래스는 각 단계에 해당하는 메서드를 순서대로 실행만 해주는 클래스이다.
또한, 단계에 대한 메서드는 선언만 되어 있을 뿐 구현되지 않았기 때문에 해당 클래스는 추상 클래스이다.
#title()
, #content()
, #footer()
: 아직 구현되지 않은 추상 메서드이다.
class diagram에서 추상 클래스와 추상 메서드는 클래스 명과 매서드 명을 이탤릭체로 표현한다. (나름 이탤릭체로 적었지만,,, ㅠ)
SimpleReturnNote
, EditableReturnNote
: NoteTemplate
클래스를 상속받아서 각 단계에 대한 추상 매서드를 구현한다.
Note
: NoteTemplate
or SimpleReturnNote
or EditableReturnNote
클래스에서 처리할 데이터를 얻을 수 있는 클래스이다.
class diagram를 바탕으로 작성한 코드이다.
note.ts
출력할 데이터 제공하는 클래스이다.
export default class Note {
constructor(
private title: string,
private content: string[],
private footer: string
) {}
public getTitle(): string {
return this.title;
}
public getContent(): string[] {
return this.content;
}
public getFooter(): string {
return this.footer;
}
}
NoteTemplate.ts
각 단계에 실행 순서에 대한 템플릿을 제공하는 추상 클래스이다.
import Note from "./note";
export default abstract class NoteTemplate {
constructor(protected note: Note) {}
// 각 단계를 정해진 순서대로 호출해주는 template 메서드 추가
public readonly display = () => {
return [this.title(), this.content(), this.footer()];
};
// title, content, footer 매서드를 구현이 없는 추상 매서드로 선언
protected abstract title(): string;
protected abstract content(): string;
protected abstract footer(): string;
}
simpleReturnNote.ts
NoteTemplate 추상 클래스를 구현하는 SimpleReturnNote 클래스이다
NoteTemplate에 3개의 추상 매서드를 입력한다.
import NoteTemplate from "./noteTemplate";
import Note from "./note";
export default class SimpleReturnNote extends NoteTemplate {
protected title(): string {
return this.note.getTitle();
}
protected content(): string {
const items = this.note.getContent().map((item) => item);
return items.join(",");
}
protected footer(): string {
return this.note.getFooter();
}
constructor(note: Note) {
super(note);
}
}
editableReturnNote.ts
import NoteTemplate from "./noteTemplate";
import Note from "./note";
export default class EditableReturnNote extends NoteTemplate {
protected title(): string {
return "수정" + this.note.getTitle();
}
protected content(): string {
const items = this.note.getContent().map((item) => `${item} 수정`);
return items.join(" ,");
}
protected footer(): string {
return "수정" + this.note.getFooter();
}
constructor(note: Note) {
super(note);
}
}
index.ts
import EditableReturnNote from "./editableReturnNote";
import Note from "./note";
import SimpleReturnNote from "./simpleReturnNote";
const note = new Note("제목", ["내용1", "내용2", "내용3"], "완료");
const simpleDisplay = new SimpleReturnNote(note);
const editDisplay = new EditableReturnNote(note);
console.log(simpleDisplay.returnString());
console.log(editDisplay.returnString());
출력 결과
탬플릿 메소드 패턴은 어떤 기능을 구성하는 각 실행 순서(or 단계)를 마치 템플릿 처럼 미리 정의해두고,
각 실행 단계에 대한 구체적인 코드를 재정의할 수 있는 유연성을 제공한다.
예제로 대입해보면
NoteTemplate
클래스에 템플릿을 필요한 기능들을 정의해두고,
NoteTemplate
을 상속 받은 SimpleReturnNote
, EditableReturnNote
에서 필요 기능(추상 매서드)들을 각 클래스의 역할에 맞게 정의해서 사용하면 된다.
예시코드에는 이해를 위해 간단하게 "수정" 정도로 나눴지만,
좀더 사용성있게 하려면 EditableReturnNote
에서는 직접 html을 수정하는 코드를 넣어도 될 것이다.
참고 자료