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

[C#/Unity][디자인패턴] 메멘토 패턴(Memento Pattern)

by 스테디코디스트 2023. 12. 21.
반응형

1. 메멘토 패턴이란?

- 객체를 이전 상태로 되돌릴 수 있는 기능을 제공하는 패턴.

- 객체의 상태 정보를 저장하고 사용자의 필요에 의해 원하는 시점의 데이터를 복원할 수 있는 패턴.

- 캡슐화를 유지하면서 객체 내부 상태를 외부에 저장하는 방법.

 

2. 메멘토 패턴을 사용하는 경우

- 어떤 객체의 상태를 변경하고, 이 변경 내용을 이후에 취소하거나 이전 상태로 복원하려고 할 때 사용

- 객체의 field, getter, setter들을 직접 접근하는 것이 해당 객체의 캡슐화를 위반할 때 사용

 

3. 메멘토 패턴의 장점

- 객체의 모든 정보를 외부로 노출시키지 않고 캡슐화를 지킬 수 있다.

- 캡슐화를 위반하지 않고 객체의 상태 스냅샷들을 생성할 수 있다.

- 코드를 단순화 시킬 수 있다.

 

4. 메멘토 패턴의 단점

- 이전 상태의 객체를 저장하기 위한 Originator가 클 경우 많은 메모리가 필요하다.

- 상태를 저장하고 복구하는데 시간이 오래 걸릴 수 있다.

- CareTaker들이 더 이상 쓸모없는 Memento들을 파괴할 수 있도록 Originator의 수명 주기를 추적해야한다.

 

5. 코드 구현

1) 구조

- Originator 

: 본래의 상태를 가지고 있고 상태를 저장하고 복원하고 싶어하는 객체

- Memento 

: Immutable(불변)한 객체로 일정 시점의 Originator의 내부정보를 가지고 있다.

- CareTaker

: Originator의 내부정보를 Memento type으로 가지고 있고 복원을 할 수 있는 객체이다.

 

2) 소스코드(C#)

using Microsoft.Win32;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace StudyCSharp
{
    // Originator - 현재 state를 가지고 있음, Memento 객체와 Memento 객체 상태를 얻게 함.
    public class Originator
    {
        private string _state;
        public string State { get => _state; set => _state = value; }

        public Memento saveStateToMemento()
        {
            return new Memento(_state);
        }

        public void getStateFromMemento(Memento memento)
        {
            _state = memento.State;
        }
    }

    // Memento - State를 가진 인스턴스
    public class Memento
    {
        private string _state;
        public string State { get => _state; }
        
        public Memento(string state)
        {
            this._state = state;
        }

    }

    // CareTaker - Memento를 순서대로 저장
    public class CareTaker
    {
        private List<Memento> _mementoList = new List<Memento>();
        public List<Memento> MementoList { get => _mementoList; }

        public void add(Memento state)
        {
            _mementoList.Add(state);
        }        
    }

    class Program
    {
        static void Main(string[] args)
        {
            Originator originator = new Originator();
            CareTaker careTaker = new CareTaker();

            originator.State = "State # 1";
            
            originator.State = "State # 2";            
            careTaker.add(originator.saveStateToMemento()); // 2번 상태 저장

            originator.State = "State # 3";
            careTaker.add(originator.saveStateToMemento()); // 3번 상태 저장

            originator.State = "State # 4";

            Console.WriteLine("Current State : {0}", originator.State);
            Console.WriteLine("-----------------------------------------------------");

            originator.getStateFromMemento(careTaker.MementoList[0]);
            Console.WriteLine("First saved State : {0}", originator.State);
            Console.WriteLine("-----------------------------------------------------");

            originator.getStateFromMemento(careTaker.MementoList[1]);
            Console.WriteLine("Second saved State : {0}", originator.State);
            Console.WriteLine("-----------------------------------------------------");
        }
    }    
}

 

- 실행 결과

 

3) 소스코드(C#)

using Microsoft.Win32;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace StudyCSharp
{
    // Originator - Player의 정보를 가지고 있음, 저장 및 불러오기를 실행할 수 있음.
    public class Player
    {
        private int _lv;
        private string _job;
        public int Lv { get => _lv; }

        public string Job { get => _job; }

        public PlayerInfo Save()
        {
            return new PlayerInfo(this._lv, this._job);
        }

        public void Undo(PlayerInfo playerInfo)
        {
            this._lv = playerInfo.Lv;
            this._job = playerInfo.Job;
        }

        public void SetInfo(int lv, string job)
        {
            this._lv = lv;
            this._job = job;
        }

        public void GetInfo()
        {
            Console.WriteLine("<<현재 상태>>");
            Console.WriteLine("현재 레벨 : {0}", this._lv);
            Console.WriteLine("현재 직업 : {0}", this._job);
            //Console.WriteLine("--------------------------------------------------");
        }
    }

    // Memento - Player의 정보를 가지고 있음.
    public class PlayerInfo
    {
        private int _lv;
        private string _job;

        public int Lv { get => _lv;}

        public string Job { get => _job; }

        public PlayerInfo(int lv, string job)
        {
            _lv = lv;
            _job = job;
        }
    }

    // CareTaker - 저장된 PlayerInfo를 가지고 있음.
    public class SaveInfo
    {
        private List<PlayerInfo> _playerInfoList = new List<PlayerInfo>();

        public List<PlayerInfo> PlayerInfoList { get => _playerInfoList; }

        public void Add(PlayerInfo playerInfo)
        {
            _playerInfoList.Add(playerInfo);
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            Player player = new Player();
            SaveInfo saveInfo = new SaveInfo();

            // 초보자
            player.SetInfo(1, "초보자");
            saveInfo.Add(player.Save()); // 저장
            player.GetInfo();
            Console.WriteLine("\t\t\t -> 레벨업");

            // 모험가
            player.SetInfo(10, "모험가");
            saveInfo.Add(player.Save()); // 저장            
            player.GetInfo();
                     
            // 전사로 전직
            player.SetInfo(10, "전사");
            saveInfo.Add(player.Save()); // 저장                                          
            Console.WriteLine("\t\t\t -> {0} 전직", player.Job);            
            player.GetInfo();

            // 전직 취소
            Console.WriteLine("\t\t\t -> 전직 이전 상태로 복귀");
            player.Undo(saveInfo.PlayerInfoList[1]); // 불러오기
            player.GetInfo();

            // 마법사로 전직
            player.SetInfo(10, "마법사");
            saveInfo.Add(player.Save()); // 저장
            Console.WriteLine("\t\t\t -> {0} 전직", player.Job);                        
            player.GetInfo();

            // 초기화
            Console.WriteLine("\t\t\t -> 초기화");
            player.Undo(saveInfo.PlayerInfoList[0]);
            player.GetInfo();

            // 전사 불러오기
            Console.WriteLine("\t\t\t -> 전사로 되돌림");
            player.Undo(saveInfo.PlayerInfoList[2]);
            player.GetInfo();

            Console.WriteLine();
        }
    }    
}

 

- 실행 결과


<참고 사이트>

 

 

18. 메멘토 패턴 (memento pattern)

메멘토 패턴 캡슐화를 유지하면서 객체 내부 상태를 외부에 저장하는 방법 --> 객체 상태를 외부에 저장했다가 해당 상태로 다시 복귀할 수 있다. originator : 우리가 저장할 객체이다. 즉 originator

kingchan223.tistory.com

 

[디자인패턴] 메멘토패턴

1. 메멘토패턴(memento pattern)이란? 메멘토패턴은 객체 내부의 상태를 외부에 저장을 하고 저장된 상태를 다시 복원하고자 할 때에 사용하는 패턴이다. 메멘토패턴을 사용함으로써 객체의 모든 정

straw961030.tistory.com

 

[Design Pattern] Memento(메멘토) 패턴이란?

행위 패턴(Behavioral Pattern) 메멘토 패턴(Memento Pattern)은 소프트웨어 디자인 패턴 중 하나로, 객체의 상태를 저장하고 나중에 복원할 수 있는 메커니즘을 제공합니다. 이 패턴은 보통 다음과 같은

shan0325.tistory.com

 

[Design Pattern] 메멘토 패턴 (Memento Pattern)

행위(Behavioral) 패턴객체의 상태 정보를 가지는 클래스를 따로 생성하여, 객체의 상태를 저장하거나 이전 상태로 복원할 수 있게 해주는 패턴원하는 시점의 상태 복원이 가능하다Originator.classOrigi

velog.io

 

 

14 메멘토 패턴 (Memento Pattern)

메멘토 패턴 (Memento Pattern) 메멘토 패턴은 객체의 상태 정보를 저장하고 사용자의 필요에 의하여 원하는 시점의 데이터를 복원 할 수 있는 패턴을 의미합니다. ■메멘토 패턴 예제 구조 ▶ 실제

lktprogrammer.tistory.com

 

메멘토 패턴

/ 디자인 패턴들 / 행동 패턴 메멘토 패턴 다음 이름으로도 불립니다: 스냅샷, Memento 의도 메멘토는 객체의 구현 세부 사항을 공개하지 않으면서 해당 객체의 이전 상태를 저장하고 복원할 수 있

refactoring.guru

 

메멘토 패턴 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 메멘토 패턴(memento pattern)은 객체를 이전 상태로 되돌릴 수 있는 기능을 제공하는 소프트웨어 디자인 패턴이다. (롤백을 통한 실행 취소) 메멘토 패턴은 3개의

ko.wikipedia.org