Template Method

최완식·2023년 2월 21일
0

Design Patterns

목록 보기
25/26
post-thumbnail

GoF의 디자인 패턴, 템플릿 메서드 패턴에 대해 알아본다.

해당 글은, 다음의 코드를 기반으로 이해하는 것이 편리합니다.

핵심 요약

  • 하나의 기능을 수행하는데 단계가 정해져 있을 시 (템플릿)
  • 이를 구현과 분리하여 처리할 수 있도록 하는 패턴

예시

Code

main

//
//  main.swift
//  TemplateMethod
//
//  Created by Choiwansik on 2023/02/21.
//

import Foundation

internal func main() {
    let title = "템플릿 메서드"

    let content = [
        "하고 있는데 졸리네요ㅕ",
        "얼마 남지 않았으니 끝을 봐야합니다..",
        "오늘은 230221",
        "벌써 2월",
    ]

    let footer = "나는 완숙"

    let article = Article(title: title, content: content, footer: footer)

    let simple = SimpleDisplayArticle(article: article)
    let caption = CaptionDisplayArticle(article: article)

    simple.display()
    print()
    caption.display()
}

main()
템플릿 메서드
하고 있는데 졸리네요ㅕ
얼마 남지 않았으니 끝을 봐야합니다..
오늘은 230221
벌써 2월
나는 완숙

Title: 템플릿 메서드
Content: 
하고 있는데 졸리네요ㅕ
얼마 남지 않았으니 끝을 봐야합니다..
오늘은 230221
벌써 2월
Footer: 나는 완숙

Article

//
//  Article.swift
//  TemplateMethod
//
//  Created by Choiwansik on 2023/02/21.
//

import Foundation

public struct Article {

    internal let title: String
    internal let content: [String]
    internal let footer: String
    
}

DisplayArticleTemplate

//
//  DisplayArticleTemplate.swift
//  TemplateMethod
//
//  Created by Choiwansik on 2023/02/21.
//

import Foundation

internal protocol DisplayArticleTemplate {

    func display()

    func title()
    func content()
    func footer()

}

extension DisplayArticleTemplate {

    internal func display() {
        self.title()
        self.content()
        self.footer()
    }

}

SimpleDisplayArticle

//
//  SimpleDisplayArticle.swift
//  TemplateMethod
//
//  Created by Choiwansik on 2023/02/21.
//

import Foundation

internal class SimpleDisplayArticle: DisplayArticleTemplate {

    internal init(article: Article) {
        self.article = article
    }

    internal func title() {
        print(self.article.title)
    }

    internal func content() {
        self.article.content.forEach { print($0) }
    }

    internal func footer() {
        print(self.article.footer)
    }

    private let article: Article

}

CaptionDisplayArticle

//
//  CaptionDisplayArticle.swift
//  TemplateMethod
//
//  Created by Choiwansik on 2023/02/21.
//

import Foundation

internal class CaptionDisplayArticle: DisplayArticleTemplate {

    internal init(article: Article) {
        self.article = article
    }

    internal func title() {
        print("Title: \(self.article.title)")
    }

    internal func content() {
        print("Content: ")
        self.article.content.forEach { print($0) }
    }

    internal func footer() {
        print("Footer: \(self.article.footer)")
    }

    private let article: Article

}

활용성

  • 알고리즘의 구조는 고정되어 있으나, 일부 단계가 다양한 구현을 필요로 하는 경우.
  • 여러 클래스에서 공통으로 사용되는 알고리즘이 있을 때, 중복 코드를 제거하고 재사용성을 높이기 위해 사용하는 경우.
  • 알고리즘의 구조와 일부 단계는 고정되어 있지만, 다른 일부 단계를 선택적으로 수행해야 할 때 사용하는 경우.

결과

  1. hook 연산을 통해, 알고리즘의 일부 단계를 선택적으로 수행할 수 있다.
  2. 코드 중복을 제거할 수 있다.
  3. 알고리즘의 구조를 명확하게 분리할 수 있다.
  4. 각 단계의 책임을 명확히 할 수 있다.

다만, 알고리즘의 구조가 간단한 경우, 굳이 이 패턴을 사용할 필요는 없다.

Reference

profile
Goal, Plan, Execute.

0개의 댓글