Problem statement :
• Consider
creating an gaming application, which
contains level 1 to 5.
• The
player will score different scores and
points at each level.
• When
the player reaches Level 1 the application will update the Score and Level (ex:
Level =1 ; Score = 100 and other points).
• When
the player reaches Level 2 the application
will update the Score and Level (ex: Level =2 ; Score = 200 and other
points).
• When
the player reaches Level 3 the application
will update the Score and Level (ex: Level =3 ; Score = 300 and other
points).
• When
the player reaches Level 4 he scores 350
but he has lost a game life .
• Now
the application should restrict
moving further level and should restore
back to Level 3 with the Score = 300 and points, but it cannot as the
application doesn't know the previous level
Score and points as they are already updated.
• To
overcome the above issue, we can use the Memento pattern.
What is Memento :
• Memento – Reminder, token, trophy. “Object to you keep to remember a person, place ,event”.
• Memento pattern falls under behavioral pattern category. – Behavioral design patterns are concerned with the interaction and responsibility of objects.
• The memento pattern is a software design pattern that provides the ability to restore an object to its previous state (undo via rollback)
• Memento means a reminder of past events . In Memento pattern, we do not create a copy of an object. We create Mementos that hold the state of an object and it might include full object or elements of an object that needs to be stored.
• Memento protects encapsulation and avoids exposing originator's internal state and implementation.
Implementation :
• Originator : Class to hold the main data (level , score
and points), i.e the data of the player
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MementoPattern
{
/// <summary>
/// Orignator class
/// </summary>
public class PlayerStatistics
{
public int LevelID { get; set; }
public int Score { get; set; }
public DateTime Time { get; set; }
public int Name { get; set; }
public int Points { get; set; }
public string GraphicType { get; set; }
/// <summary>
/// Save the player statics to a memento
/// </summary>
/// <param name="playerStatistics"></param>
/// <returns></returns>
public PlayerStatisticsMemento CreateMemento(PlayerStatistics playerStatistics)
{
return new PlayerStatisticsMemento(playerStatistics.LevelID, playerStatistics.Score, playerStatistics.Time, playerStatistics.Points);
}
/// <summary>
/// Restore the player statistics to a previous state held by memento
/// </summary>
/// <param name="checkPointMemento"></param>
public void SetMemento(PlayerStatisticsMemento checkPointMemento)
{
this.LevelID = checkPointMemento._LevelID;
this.Score = checkPointMemento._Score;
this.Time = checkPointMemento._Time;
}
public void PrintStatistics()
{
Console.WriteLine("CheckPoint Time:" + this.Time);
Console.WriteLine("Level is:" + this.LevelID);
Console.WriteLine("Score is:" + this.Score);
}
}
}
• Memento : Class used to store the snapshot of the origin data (Originator class) only with the properties
which are needed to be captured.
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Text;
5: using System.Threading.Tasks;
6: namespace MementoPattern
7: {
8: /// <summary>
9: /// Memento
10: /// </summary>
11: public class PlayerStatisticsMemento
12: {
13: public int _LevelID { get; set; }
14: public int _Score { get; set; }
15: public DateTime _Time { get; set; }
16: public int _Points { get; set; }
17: public PlayerStatisticsMemento(int level, int score, DateTime time, int points)
18: {
19: this._LevelID = level;
20: this._Score = score;
21: this._Time = time;
22: this._Points = points;
23: }
24: }
25: }
• CareTaker : To hold all the memento objects , i.e
which holds the snapshot of the original data.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MementoPattern
{
/// <summary>
/// Caretaker to hold the undo/redo.
/// </summary>
public class CareTaker
{
private static CareTaker _instance;
private PlayerStatisticsMemento _playerStaticsMemento;
private CareTaker()
{
}
public static CareTaker Instance
{
get
{
if (_instance == null)
{
_instance = new CareTaker();
}
return _instance;
}
}
public PlayerStatisticsMemento PlayerStaticsMemento
{
get
{
return _playerStaticsMemento;
}
set
{
_playerStaticsMemento = value;
}
}
}
}
Main program:
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Text;
5: using System.Threading.Tasks;
6: namespace MementoPattern
7: {
8: class Program
9: {
10: static void Main(string[] args)
11: {
12: PlayerStatistics _statistics = new PlayerStatistics();
13: _statistics.LevelID = 1;
14: _statistics.Score = 100;
15: _statistics.Time = DateTime.Now;
16: _statistics.PrintStatistics();
17: _statistics.LevelID = 2;
18: _statistics.Score = 200;
19: _statistics.Time = DateTime.Now;
20: _statistics.PrintStatistics();
21: _statistics.LevelID = 3;
22: _statistics.Score = 300;
23: _statistics.Time = DateTime.Now;
24: _statistics.PrintStatistics();
25: CareTaker.Instance.PlayerStaticsMemento = _statistics.CreateMemento(_statistics);
26: _statistics.LevelID = 4;
27: _statistics.Score = 350;
28: _statistics.Time = DateTime.Now;
29: _statistics.PrintStatistics();
30: Console.WriteLine("\nPlayer lost his life here so retore to level 3\n");
31: _statistics.SetMemento(CareTaker.Instance.PlayerStaticsMemento);
32: _statistics.PrintStatistics();
33: Console.ReadLine();
34: }
35: }
36: }
UML Diagram :
Benefit & Examples:
1. Improve Performance:
• Sine value
calculation.
2. Undo/Roll back Operations:
• Ctrl-Z in MS
Word
• Bank Transaction
• Cancel operation
in Forms