목차
메멘토(Memento)
메멘토 디자인 패턴은 객체의 상태를 특정 시점에 캡처하여 나중에 해당 상태로 객체를 복원할 수 있도록 하는 디자인 패턴이다. 이 패턴의 명칭은 '기억을 보존하는 것'을 의미하는 라틴어 'Memento'에서 유래했다. 이 패턴은 주로 되돌리기 기능이나 스냅샷, 상태 복원 기능이 필요할 때 유용하게 사용된다.
메멘토 패턴은 크게 세 가지 기본 구성요소로 이루어져 있다:
- Originator(발생자): 자신의 상태를 저장하거나 복원할 수 있는 객체.
- Memento(메멘토): 발생자의 상태를 저장하는 객체. 발생자 외에는 이 객체에 접근할 수 없어야 한다.
- Caretaker(케어테이커): 메멘토를 저장하는 객체. 메멘토의 내용을 조작하거나 직접 접근하지 않고, 메멘토를 관리(저장하거나 복원 요청)하는 역할만 수행한다.
패턴 미적용 예시
간단한 게임에서 플레이어의 상태(예: 위치, 체력 등)를 저장하고 복원하는 기능을 구현하지 않고, 게임 상태를 직접 조작하는 예시를 생각해볼 수 있다. 이 경우, 게임의 복잡성이 증가할수록 상태 관리의 어려움이 커지고, 상태 복원이나 되돌리기 기능 구현이 어려워진다.
class Player
{
public int Health { get; set; }
public string Position { get; set; }
// 플레이어 상태 변경
public void TakeDamage(int damage)
{
Health -= damage;
}
// 플레이어 위치 변경
public void MoveTo(string newPosition)
{
Position = newPosition;
}
}
class Game
{
public void ProcessGame()
{
Player player = new Player() { Health = 100, Position = "Start" };
// 게임 로직 처리
player.TakeDamage(10); // 플레이어가 데미지를 받음
player.MoveTo("Forest"); // 플레이어 위치 이동
// 상태 복원 로직이 없어 특정 시점의 상태로 되돌리기 어려움
}
}
이 코드에서는 Player 객체의 상태(체력, 위치)를 변경하는 메서드가 있지만, 특정 시점의 상태를 저장하거나 복원하는 기능이 구현되어 있지 않다. 이로 인해 발생하는 문제는 다음과 같다:
- 상태 복원 또는 되돌리기 기능이 필요할 때 추가 구현이 복잡해진다.
- 상태 관리의 어려움이 증가한다.
메멘토 패턴 적용 예시
이제 같은 상황에서 메멘토 패턴을 적용하여 플레이어의 상태를 저장하고, 원하는 시점으로 되돌릴 수 있도록 구현한 예시를 살펴보자. 메멘토 패턴을 사용함으로써, 플레이어의 상태 관리를 보다 유연하고 효율적으로 할 수 있다.
메멘토 패턴 구성 요소
- Originator(발생자): Player 클래스가 이 역할을 수행하며, 자신의 상태를 저장하고 복원하는 기능을 가진다.
- Memento(메멘토): PlayerMemento 클래스는 플레이어 상태의 스냅샷을 저장한다. 이 클래스는 Player 클래스의 상태를 그대로 보관하지만, 외부에서는 접근할 수 없도록 캡슐화한다.
- Caretaker(케어테이커): GameCaretaker 클래스가 이 역할을 수행하며, 메멘토 객체를 저장하고 관리한다. 실제 메멘토의 내용은 직접 조작하지 않고, 필요한 시점에 Originator에게 전달하여 상태를 복원한다.
using System;
using System.Collections.Generic;
// Originator
class Player
{
public int Health { get; set; }
public string Position { get; set; }
// 현재 상태를 저장하고 메멘토 객체를 생성한다.
public PlayerMemento SaveState()
{
return new PlayerMemento(Health, Position);
}
// 메멘토 객체를 받아 상태를 복원한다.
public void RestoreState(PlayerMemento memento)
{
Health = memento.Health;
Position = memento.Position;
}
}
// Memento
class PlayerMemento
{
public int Health { get; private set; }
public string Position { get; private set; }
public PlayerMemento(int health, string position)
{
Health = health;
Position = position;
}
}
// Caretaker
class GameCaretaker
{
private List<PlayerMemento> savedStates = new List<PlayerMemento>();
// 상태를 저장한다.
public void SaveState(PlayerMemento memento)
{
savedStates.Add(memento);
}
// 지정된 인덱스의 상태를 복원한다.
public PlayerMemento RestoreState(int index)
{
if (index < 0 || index >= savedStates.Count)
throw new IndexOutOfRangeException("Invalid index");
return savedStates[index];
}
}
class Game
{
static void Main(string[] args)
{
Player player = new Player() { Health = 100, Position = "Start" };
GameCaretaker caretaker = new GameCaretaker();
// 초기 상태 저장
caretaker.SaveState(player.SaveState());
// 게임 로직 처리
player.TakeDamage(10);
player.MoveTo("Forest");
// 이전 상태로 복원
player.RestoreState(caretaker.RestoreState(0));
// 복원된 상태 확인
Console.WriteLine($"Health: {player.Health}, Position: {player.Position}");
}
}
이 코드에서 Player 클래스는 자신의 상태(체력, 위치)를 PlayerMemento 객체에 저장하거나, 이 객체로부터 상태를 복원하는 기능을 제공한다. GameCaretaker 클래스는 이러한 PlayerMemento 객체들을 관리하며, 게임의 필요에 따라 특정 시점의 상태를 복원할 수 있도록 한다. 메멘토 패턴을 이용함으로써, 상태의 저장과 복원을 보다 체계적이고 안전하게 관리할 수 있게 된다.
'컴퓨터 과학 > 디자인패턴' 카테고리의 다른 글
[디자인패턴] 행위 패턴(8) : 발행-구독(Publisher-Subscriber) (1) | 2024.03.25 |
---|---|
[디자인패턴] 행위 패턴(7) : 옵저버(Observer) (1) | 2024.03.25 |
[디자인패턴] 행위 패턴(5) : 중재자(Mediator) (0) | 2024.03.25 |
[디자인패턴] 행위 패턴(4) : 반복자(iterator) (2) | 2024.03.25 |
[디자인패턴] 행위 패턴(3) : 인터프리터(Interpreter) (1) | 2024.03.25 |