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
}
활용성
- 알고리즘의 구조는 고정되어 있으나, 일부 단계가 다양한 구현을 필요로 하는 경우.
- 여러 클래스에서 공통으로 사용되는 알고리즘이 있을 때, 중복 코드를 제거하고 재사용성을 높이기 위해 사용하는 경우.
- 알고리즘의 구조와 일부 단계는 고정되어 있지만, 다른 일부 단계를 선택적으로 수행해야 할 때 사용하는 경우.
결과
- hook 연산을 통해, 알고리즘의 일부 단계를 선택적으로 수행할 수 있다.
- 코드 중복을 제거할 수 있다.
- 알고리즘의 구조를 명확하게 분리할 수 있다.
- 각 단계의 책임을 명확히 할 수 있다.
다만, 알고리즘의 구조가 간단한 경우, 굳이 이 패턴을 사용할 필요는 없다.