[Behavioral Pattern] 메멘토 패턴 (Memento Pattern)
Design Pattern / Behavioral Pattern
메멘토 패턴의 정의와 해당 디자인 패턴의 예제 코드를 통한 이해 및 설명 정리
배포된 예제 사이트
개념
객체의 상태 정보를 가지는 클래스를 따로 생성하여 객체의 상태를 저장하거나, 이전 상태로 복원할 수 있게 해주는 패턴
원하는 시점의 상태로 복원 가능
패턴 구조
Originator내부 상태를 보유하고 있는 일부 객체
CareTaker는Originator에 대해 무언가를 하지만, 변경에 대한 실행 취소를 하기를 원함
CareTaker먼저
Originator에게Memento객체를 요청그 뒤, 예정된 일련의 명령을 수행
명령 이전의 상태로 되돌리기 위해
Memento객체를Originator에 반환
Memento객체 자신은 불투명 자료형
CareTaker가 변경할 수 없거나 변경해서는 안됨
예제 코드
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
class Originator {
private state: string;
constructor(state: string) {
this.state = state;
console.log(`Originator: My initail state is: ${state}`);
}
public doSomething(): void {
console.log(`Originator: I\'m doing something important`);
this.state = this.generateRandomString(30);
console.log(`Originator: and my state has changed to: ${this.state}`);
}
private generateRandomString(length: number = 10): string {
const charSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
return Array.apply(null, { length })
.map(() => charSet.charAt(Math.floor(Math.random() * charSet.length)))
.join("");
}
public save(): Memento {
return new ConcreteMemento(this.state);
}
public restore(memento: Memento): void {
this.state = memento.getState();
console.log(`Originator: My state has changed to: ${this.state}`);
}
}
interface Memento {
getState(): string;
getName(): string;
getDate(): string;
}
class ConcreteMemento implements Memento {
private state: string;
private date: string;
constructor(state: string) {
this.state = state;
this.date = new Date().toISOString().slice(0, 19).replace("T", "");
}
public getState(): string {
return this.state;
}
public getName(): string {
return `${this.date} / (${this.state.substring(0, 9)}...)`;
}
public getDate(): string {
return this.date;
}
}
class CareTaker {
private mementos: Memento[] = [];
private originator: Originator;
constructor(originator: Originator) {
this.originator = originator;
}
public backup(): void {
console.log("\nCareTaker: Saving Originator's state...");
this.mementos.push(this.originator.save());
}
public undo(): void {
if (!this.mementos.length) return;
const memento = this.mementos.pop() as Memento;
console.log(`CareTaker: Restoring state to: ${memento?.getName()}`);
this.originator.restore(memento);
}
public showHistory(): void {
console.log("CareTaker: Here's the list of mementos:");
for (const memento of this.mementos) {
console.log(memento.getName());
}
}
}
/** Client Code */
const originator = new Originator("Super-duper-super-puper-super.");
const caretaker = new CareTaker(originator);
caretaker.backup();
originator.doSomething();
caretaker.backup();
originator.doSomething();
caretaker.backup();
originator.doSomething();
console.log("");
caretaker.showHistory();
console.log("\nClient: Now, let's rollback!\n");
caretaker.undo();
console.log("\nClient: Once more!\n");
caretaker.undo();
참고한 출처 사이트
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

