Memento
2022. 3. 16. 00:00ㆍCSharp/Design Pattern
반응형
구현의 세부 사항을 공개하지 않고 개체의 이전 상태를 저장하고 복원할 수 있는 동작 디자인 패턴
문제
텍스트 편집기의 기능중에 undo 기능을 만들려고 한다고 가정해 보자
특정 command 를 하게 되면 내용을 history 에 snapshot 형태로 저장할 것이다.
비공개 필드등은 처리 하기 어렵다.
편집기 관련 class 를 수정 하게 되었을때 개체 상태를 복사하는 class를 함께 변경해야 한다.
실제 텍스트, 커서 좌표, 현재 스크롤 위치 등을 포함해야 한다.
이러한 값들은 모두 상태가 노출되어야 한다. (public)
해결책
상태 스냅샷 생성을 해당 상태의 실제 소유자인 발신자 객체에게 위임
편집기 클래스 자체가 스냅샷 생성
memento 라는 특수 객체에 객체 상태의 복사본을 저장
class diagram
오리지네이터(Originator) : 내부 상태를 보유하고 있는 일부 객체
케어테이커(Caretaker) : 오리지네이터에 실행 취소
메멘토(Memento) : 케어테이커 에서 변경할 수 없는 상태
적용
- 객체의 이전 상태를 복원할 수 있도록 객체 상태의 스냅샷을 생성하려는 경우
- 개체의 필드/게터/세터에 대한 직접 액세스가 캡슐화를 위반할 때
예제
public interface ISalesOriginator
{
SalesMemento SaveMemento();
void RestoreMemento(SalesMemento memento);
}
/// <summary>
/// The 'Originator' class
/// </summary>
public class SalesOriginator: ISalesOriginator
{
private string _name;
private string _phone;
private double _budget;
// Gets or sets name
public string Name
{
get { return _name; }
set
{
_name = value;
Console.WriteLine("Name: " + _name);
}
}
// Gets or sets phone
public string Phone
{
get { return _phone; }
set
{
_phone = value;
Console.WriteLine("Phone: " + _phone);
}
}
// Gets or sets budget
public double Budget
{
get { return _budget; }
set
{
_budget = value;
Console.WriteLine("Budget: " + _budget);
}
}
// Stores memento
public SalesMemento SaveMemento()
{
Console.WriteLine("\nSaving state --\n");
return new SalesMemento(_name, _phone, _budget);
}
// Restores memento
public void RestoreMemento(SalesMemento memento)
{
Console.WriteLine("\nRestoring state --\n");
(Name,Phone, Budget) = memento.GetRestore();
}
}
public interface ISalesMemento
{
(string Name, string Phone, double Budget) GetRestore();
}
/// <summary>
/// The 'Memento' class
/// </summary>
public class SalesMemento : ISalesMemento
{
private readonly string _name;
private readonly string _phone;
private readonly double _budget;
// Constructor
public SalesMemento(string name, string phone, double budget)
{
this._name = name;
this._phone = phone;
this._budget = budget;
}
public string Name => _name;
public string Phone => _phone;
public double Budget => _budget;
public (string Name, string Phone, double Budget ) GetRestore()
{
return (this.Name, this.Phone, this.Budget);
}
}
/// <summary>
/// The 'Caretaker' class
/// </summary>
public class SalesCaretaker
{
public SalesMemento Memento { get; set; }
}
사용법
SalesOriginator s = new SalesOriginator();
s.Name = "Noel van Halen";
s.Phone = "(412) 256-0990";
s.Budget = 25000.0;
// Store internal state
SalesCaretaker m = new SalesCaretaker();
m.Memento = s.SaveMemento();
// Continue changing originator
s.Name = "Leo Welch";
s.Phone = "(310) 209-7111";
s.Budget = 1000000.0;
// Restore saved state
s.RestoreMemento(m.Memento);
//output
Name: Noel van Halen
Phone: (412) 256-0990
Budget: 25000
Saving state --
Name: Leo Welch
Phone: (310) 209-7111
Budget: 1000000
Restoring state --
Name: Noel van Halen
Phone: (412) 256-0990
Budget: 25000
관련영상
반응형
'CSharp > Design Pattern' 카테고리의 다른 글
Template Method (0) | 2022.03.18 |
---|---|
State (0) | 2022.03.17 |
Iterator (0) | 2022.03.15 |
Chain of Responsibility (0) | 2022.03.14 |
Proxy (0) | 2022.03.11 |