[디자인 패턴] - 03. 탬플릿 메서드(Template Method) 패턴

gyomni·2023년 5월 8일
1

design pattern

목록 보기
3/3
post-thumbnail

Template Method

어떤 기능에 대해서 실행 되어야 할 각 단계에 대한 순서만을 일단 정해두고, 각 단계에 대한 세부 구현을 상황에 따라 다르게 구현할 수 있도록 하는 패턴이다.

예시로 패턴을 이해해 보자.

예시

class diagram

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을 수정하는 코드를 넣어도 될 것이다.

참고 자료

profile
Front-end developer 👩‍💻✍

0개의 댓글