Хадгалагч (Memento) хэв обьектын дотоод төлвийг түүний гадна гаргаж дараа нь хайрцаглалтын зарчмыг зөрчихгүйгээр обьектыг сэргээх боломжийг олгодог.
Хэвийг хаана ашиглах
- Дараа нь сэргээх боломжтойгоор обьектын төлвийг хадгалах хэрэгтэй бол
- Обьектын төлвийн хадгалалт хайрцаглалтын зарчмыг зөрчихгүйгээр хийгдэх хэрэгтэй бол
Энэхүү хэвийн түлхүүр ойлголт нь дотоод төлөв, хайрцаглалтын зарчим хоорондын балансыг сахин хадгалах юм. Хэрвээ бид хайрцаглалтыг зөрчихгүй бол обьектын төлвийг ердийн хувьсагчид хадгалах боломжтой шүү дээ. Харин эдгээр хувьсагчдад хандан утга олгох /setter/, утгыг авах /getter/ арга эсхүл шинжүүд үргэлж байгаад байдаггүй. Жишээ нь тоглоомд баатрыг удирддаг. Баатрын зэвсэг, амины хэмжээ, хүч гэх мэтээр бусад үзүүлэлтүүд тухайн баатрын обьект дотор агуулагддаг. Сүүлд өмнөх түвшиндээ буцан тоглоомыг шинээр эхлүүлэхийн тулд эдгээр бүх үзүүлэлтийг гадна хадгалах тохиолдол олонтаа гардаг. Энэ тохиолдолд хадгалагч хэв тусалж болно.
Хэвийн бүтцийн диаграмыг дараах байдлаар дүрсэлж болно.
Хэвийн бүтцийг C# -аар харуулбал
class Memento
{
public string State { get; private set;}
public Memento(string state)
{
this.State = state;
}
}
class Caretaker
{
public Memento Memento { get; set; }
}
class Originator
{
public string State { get; set; }
public void SetMemento(Memento memento)
{
State = memento.State;
}
public Memento CreateMemento()
{
return new Memento(State);
}
}
Оролцогчид
- Memento - Originator обьектын төлвийн хадгалагч ба зөвхөн энэхүү Originator обьетод бүрэн хандалтыг олгоно.
- Originator - өөрийн төлвийг хадгалах хадгалагч обьектыг үүсгэнэ.
- Caretaker - зөвхөн Memento обьектыг хадгалах үүргийг гүйцэтгэх бөгөөд түүнд хадгалагчид хандах бүрэн эрх байхгүй. Өөрөөр хэлбэл класс хадгалах үйлдлээс өөр юуг ч хийж чадахгүй.
Одоо бодит жишээ авч үзье. Бидэнд тоглоомын баатрын төлвийг хадгалах хэрэг гарлаа гэе.
class Program
{
static void Main(string[] args)
{
Console.OutputEncoding = Encoding.UTF8;
Hero hero = new Hero();
hero.Shoot(); // Буудлага хийлээ, 9 сум үлдсэн
GameHistory game = new GameHistory();
game.History.Push(hero.SaveState()); // тоглоомыг хадгалах
hero.Shoot(); // Буудлага хийлээ, 8 сум үлдсэн
hero.RestoreState(game.History.Pop());
hero.Shoot(); // Буудлага хийлээ, 8 сум үлдсэн
Console.Read();
}
}
// Originator
class Hero
{
private int patrons = 10; // сумны тоо
private int lives = 5; // амины тоо
public void Shoot()
{
if (patrons > 0)
{
patrons--;
Console.WriteLine("Буудлаа. {0} сум үлдсэн", patrons);
}
else
Console.WriteLine("Сум дууссан");
}
// төлвийн хадгалалт
public HeroMemento SaveState()
{
Console.WriteLine("Тоглоомыг хадгалах. Параметрүүд: {0} сум, {1} амь", patrons, lives);
return new HeroMemento(patrons, lives);
}
// төлвийн сэргээлт
public void RestoreState(HeroMemento memento)
{
this.patrons = memento.Patrons;
this.lives = memento.Lives;
Console.WriteLine("Тоглоомыг сэргээх. Параметрүүд: {0} сум, {1} амь", patrons, lives);
}
}
// Memento
class HeroMemento
{
public int Patrons { get; private set; }
public int Lives { get; private set; }
public HeroMemento(int patrons, int lives)
{
this.Patrons = patrons;
this.Lives = lives;
}
}
// Caretaker
class GameHistory
{
public Stack<HeroMemento> History { get; private set; }
public GameHistory()
{
History = new Stack<HeroMemento>();
}
}
Програмыг ажлуулбал
үр дүн гарна. Энд Originator -ийн үүргийг төлөв нь сум, амины тоогоор тодорхойлогдох Hero класс гүйцэтгэнэ. HeroMemento класс тоглоомын баатрын төлвийг хадгалахад зориулагдсан. Hero обьект өөрийн төлвийг SaveState() аргаар HeroMemento -д хадгалаад RestoreState() аргаар сэргээнэ. GameHistory класс төлвийг хадгалахад зориулагдсан бөгөөд бүх төлвүүдийг стекд хадгалах тул сүүлийн төлвийг амархан гарган ирэх боломжтой.
Memento хэв дараах давуу талтай.
- Системийн холбоог багасгана
- Мэдээллийг хайрцаглан хадгална
- Төлвийг хадгалах, сэргээхэд энгийн интерфейсийг тодорхойлно
Хэрвээ их хэмжээний мэдээллийг хадгалах хэрэгтэй болбол бүх төлвийг хадгалахад зардал /хугацаа, санах ой/ ихсэх тул нөөцийн дутагдалтай тулгарч мэднэ.