본문 바로가기
STUDY/디자인패턴

Memento 메멘토 패턴 ★

by 램플릿 2024. 7. 19.

상태를 보관해놨다가 롤백할 때 사용. 커맨드 패턴과 섞어서 자주 사용한다.

(커맨드 패턴이 안쓰면 잘 쓸일이 없다....)

 

메멘토 : 단순하게 내 상태를 저장할 수 있는 커맨드 패턴과 매우 유사하다.

변한 변수를 넣어놨다가 필요할 때 되돌리기

 

데이터를 변환한 다음에 변환된 상태를 저장해놓고, 예전으로 돌아가고싶을 때 초기상태로 다시 돌아간다.

 

스택의 Peek은 스택 맨 위에 있는 데이터를 말한다.

using UnityEngine;
using System.Collections.Generic;

// Memento 클래스: 플레이어의 상태를 저장
public class Player_1Memento
{
    public Vector3 Position { get; private set; }
    public int Health { get; private set; }
    public int Score { get; private set; }

    public Player_1Memento(Vector3 position, int health, int score)
    {
        Position = position;
        Health = health;
        Score = score;
    }
}

// Originator 클래스: 플레이어
public class Player_1 : MonoBehaviour
{
    public Vector3 Position { get; set; }
    public int Health { get; set; }
    public int Score { get; set; }

    // 현재 상태를 Memento에 저장
    public Player_1Memento SaveState()
    {
        return new Player_1Memento(Position, Health, Score);
    }

    // Memento로부터 상태를 복원
    public void RestoreState(Player_1Memento memento)
    {
        Position = memento.Position;
        Health = memento.Health;
        Score = memento.Score;

        // Unity Transform 업데이트
        transform.position = Position;

        Debug.Log($"State restored - Position: {Position}, Health: {Health}, Score: {Score}");
    }

    // 플레이어 상태 변경 (예시용)
    public void ChangeState(Vector3 newPosition, int healthChange, int scoreChange)
    {
        Position = newPosition;
        Health += healthChange;
        Score += scoreChange;

        // Unity Transform 업데이트
        transform.position = Position;

        Debug.Log($"State changed - Position: {Position}, Health: {Health}, Score: {Score}");
    }
}

// Caretaker 클래스: 메멘토 관리
public class GameManager_2 : MonoBehaviour
{
    public Player_1 Player_1;
    private Stack<Player_1Memento> mementos = new Stack<Player_1Memento>();

    void Start()
    {
        Player_1 = GetComponent<Player_1>();
        SavePlayer_1State(); // 초기 상태 저장
    }

    public void SavePlayer_1State()
    {
        mementos.Push(Player_1.SaveState());
        Debug.Log("Player_1 state saved.");
    }

    public void UndoPlayer_1State()
    {
        if (mementos.Count > 1) // 항상 하나의 상태는 남겨둠
        {
            mementos.Pop(); // 현재 상태 제거
            Player_1.RestoreState(mementos.Peek());
        }
        else
        {
            Debug.Log("Can't undo: No more saved states.");
        }
    }

    // 테스트용 메서드들
    public void MovePlayer_1Randomly()
    {
        Vector3 randomPosition = Random.insideUnitSphere * 5f;
        randomPosition.y = 0; // y축은 0으로 유지

        int healthChange = Random.Range(-10, 11);
        int scoreChange = Random.Range(0, 101);

        Player_1.ChangeState(randomPosition, healthChange, scoreChange);
        SavePlayer_1State();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.S))
        {
            MovePlayer_1Randomly();
        }
        if (Input.GetKeyDown(KeyCode.U))
        {
            UndoPlayer_1State();
        }
    }
}

'STUDY > 디자인패턴' 카테고리의 다른 글

Iterator 이터레이터 패턴  (0) 2024.07.19
Mediator 메디에이터 패턴  (0) 2024.07.19
Strategy 전략 패턴  (0) 2024.07.19
Observer 옵저버 패턴 ★★★  (0) 2024.07.19
FSM(Finite-State-Machine) ★★★  (0) 2024.07.17