티스토리 뷰
[Swift 디자인 패턴] Memento Pattern (메멘토) - 디자인 패턴 공부 19
Dev_Pingu 2021. 6. 6. 17:51안녕하세요 Pingu입니다!🐧
지난 글에서는 행동 패턴 중 하나인 Mediator Pattern(중재자)에 대해 알아봤었는데요, 이번 글에서는 또 다른 행동 패턴 중 하나인 Memento Pattern(메멘토)에 대해 알아보도록 하겠습니다.
메멘토 패턴이란?
Memento Pattern은 구현의 세부 사항을 공개하지 않고, 즉 캡슐화를 위반하지 않고 객체의 이전 상태를 저장하고 복원할 수 있는 디자인 패턴입니다.
- Originator
- 자체적으로 현재의 state를 저장하는 Memento 객체를 생성할 수 있습니다.
- State를 복원하기 위해 Memento를 사용합니다.
- Memento
- Originator의 state에 대한 스냅샷 역할을 하는 객체입니다.
- Originator 이외 객체의 접근으로부터 보호합니다.
- Memento를 immutable하게 만들고 생성자를 통해 데이터를 한 번만 전달합니다.
- Care Taker
- Memento 객체들을 저장하여 Originator의 동작을 추적합니다.
- Memento의 내용을 조작하거나 검토하지 않습니다.
메멘토 패턴은 언제 쓰나요?
프로그래밍을 하다 보면 객체의 내부 상태를 기록해둬야 할 때가 있습니다. 이러한 상황에는 오류에서 복구할 수 있도록 하거나 텍스트 편집기에서 실행 취소 기능을 구현할 때 필요할 거예요. 이러한 상황에서 객체의 상태를 기록해줘야 하는데 이를 외부에 저장하거나 다른 객체에서 접근 가능하도록 하면 캡슐화를 위반하게 됩니다. 즉 상태를 저장할 클래스의 모든 내부 정보를 노출하지 않고 이러한 상태에 접근하는 것을 제한해줘야 하는데 이럴 때 메멘토 패턴을 사용할 수 있습니다.
Memento Pattern에서 State를 기록하는 Originator 객체가 State를 기록하고 이를 Memento 객체에 저장합니다. Memento 객체는 Originator 객체를 제외하고는 접근 할 수 없도록 만듭니다. 이러한 Memento 객체들은 Caretaker라는 객체에 저장되며 Caretaker는 제한된 인터페이스를 통해서 Memento 객체를 다루기 때문에 Memento 객체의 내부를 조작할 수 없습니다. 하지만 Originator는 Memento 객체에 자유롭게 접근할 수 있기 때문에 원하는 State로 복원할 수 있게 됩니다.
메멘토 패턴의 결과
장점
- 캡슐화를 위반하지 않고 객체의 state 스냅샷을 생성할 수 있습니다.
- Caretaker가 Originator의 State 기록을 유지하므로 Originator의 코드가 단순화됩니다.
단점
- 클라이언트가 Memento 객체를 너무 많이 생성하면 메모리가 많이 사용됩니다.
- Caretaker는 오래된 memento 객체를 삭제 할 수 있도록 Originator의 생명 주기를 추적해야 합니다. 즉 자원을 소비해야 합니다.
- 몇몇 언어에서는 Originator만 Memento 객체에 접근할 수 있도록 만드는 것이 어려울 수 있습니다.
예제
그럼 Memento Pattern을 Swift 언어로 간단하게 구현해보도록 하겠습니다.
여러 가지 게임에서 Save, Load 기능이 있는데, 게임을 save 하고 load 하는 기능을 메멘토 패턴으로 구현하기에 재밌어 보여서 한 번 구현해볼게요.
먼저 Originator 역할을 하는 Game 클래스를 정의합니다.
// Originator
class Game {
var level: Int = 0
var score: Int = 0
func setLevel(level: Int) {
self.level = level
}
func setScore(score: Int) {
self.score = score
}
func makeSnapshot() -> SaveData {
print("Level : \(self.level), Score: \(self.score) 상태를 저장합니다.\n")
return SaveData(originator: self)
}
func printCurrentState() {
print("현재 상태 Level : \(self.level), Score: \(self.score)")
}
}
방금 정의한 Game의 객체 상태를 저장할 Memento 클래스를 하나 정의합니다.
// Memento
class SaveData {
var originator: Game
var level: Int = 0
var score: Int = 0
init(originator: Game) {
self.originator = originator
self.level = originator.level
self.score = originator.score
}
func load() {
self.originator.setLevel(level: self.level)
self.originator.setScore(score: self.score)
}
}
Memento 객체 역할을 하는 SaveData 클래스에는 load라는 메서드를 만들어 해당 memento 객체의 상태로 originator의 상태를 복원할 수 있도록 만들었어요.
마지막으로 Caretaker 클래스를 정의해줍니다.
// Caretaker
class GameDataSystem {
private var history: [SaveData] = []
func save(snapshot: SaveData) {
self.history.append(snapshot)
}
func load() {
if let snapshot = self.history.popLast() {
print("최근 저장 상태를 불러옵니다.\n")
snapshot.load()
} else {
print("저장 기록이 없습니다.\n")
}
}
}
Caretaker 객체에는 Originator가 만든 Memento 객체들을 저장하고 복원을 위한 load 메서드를 정의해줍니다.
이렇게 만든 클래스들을 직접 사용하면 아래와 같이 실행됩니다.
객체의 상태를 잘 저장하고 이를 잘 불러오는 것을 볼 수 있습니다.
이렇게 Memento Pattern을 알아보고 간단하게 구현도 해봤습니다.
혹시라도 틀린 부분이 있다면 알려주시면 감사하겠습니다.
전체 코드는 여기에서 볼 수 있습니다.
감사합니다.
'Swift > Design_Pattern' 카테고리의 다른 글
[Swift 디자인패턴] State Pattern (상태) - 디자인 패턴 공부 21 (0) | 2021.06.29 |
---|---|
[Swift 디자인 패턴] Observer Pattern (옵저버) - 디자인 패턴 공부 20 (0) | 2021.06.28 |
[Swift 디자인 패턴] Mediator Pattern (중재자) - 디자인 패턴 공부 18 (0) | 2021.05.30 |
[Swift 디자인 패턴] Iterator Pattern (이터레이터) - 디자인 패턴 공부 17 (0) | 2021.05.30 |
[Swift 디자인 패턴] Interpreter Pattern (인터프리터) - 디자인 패턴 공부 16 (0) | 2021.05.29 |
- Total
- Today
- Yesterday
- 테이블뷰
- IOS
- 알고리즘
- OS
- OSTEP
- pattern
- 백준
- Xcode
- Swift
- System
- 동시성
- 자료구조
- 코딩테스트
- document
- operator
- 문법
- BFS
- Publisher
- DP
- 코테
- 아이폰
- Combine
- Apple
- dfs
- mac
- design
- operating
- 스위프트
- 앱개발
- 프로그래밍
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |