[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 라이센스를 따릅니다.