این سایت برای ie9 طراحی نشده است

لطفا دستگاه خود را بچرخانید.

الگوی طراحی – Memento

۲۷ اردیبهشت ۱۳۹۶ حسین صداقت
بدون دیدگاه

به نام خدا

همانطور که در مطلب قبل اشاره کردیم در این مطلب می خواهیم الگوی طراحی Memento را با هم مرور کنیم.کاربرد این الگوی طراحی زمانی است که ما نیاز داریم یک حالت خاص از یک شی را ذخیره کنیم تا در صورت نیاز شی را بعد از تغییر، به حالت ذخیره شده برگردانیم.همه ما کم وبیش درگیر بازی های کامپیوتری بوده ایم.Save  کردن یک بازی دقیقا حالتی است که میشه از الگوی طراحی Memento استفاده کرد.فقط نکته ای که در Memento باید مورد توجه قرار بگیره این هستش که فقط همان Object ی که Memento را ایجاد کرده است می تواند به Memento خودش دسترسی داشته باشد.

.نمودار UML  این الگو به صورت زیر است:

Memento

نقش های شرکت کننده در این الگو موارد زیر هستند :

Memento: حالت شی را ذخیره می کند.Memento بر حساب نیاز می تواند همه یا قسمتی از حالت داخلی یک شی رو ذخیره کند.همچنین در برابر دسترسی های اشیاء غیر از شی اصلی محافظت می کند.

Originator: Memento شامل یک Snapshot از حالت فعلی را ایجاد می کند.همچنین از Memento برای Restore کردن استفاده می کند.

Caretaker: مسئول حفاظت و نگهداری از Memento می باشد.همچنین هیچ عملیاتی رو محتوای Memento انجام نمی دهد.

مثال: فرض کنید ما می خواهیم یک سیستم چشم انداز فروش  کنیم و الگوی طراحی Memento را آن پیاده سازی کنیم.

ابتدا می آییم کلاس Memento را ایجاد می کنیم.

class Memento
{
  private string _name;
  private string _phone;
  private double _budget;
 
  // Constructor
  public Memento(string name, string phone, double budget)
  {
    this._name = name;
    this._phone = phone;
    this._budget = budget;
  }
 
  // Gets or sets name
  public string Name
  {
    get { return _name; }
    set { _name = value; }
  }
 
  // Gets or set phone
  public string Phone
  {
    get { return _phone; }
    set { _phone = value; }
  }
 
  // Gets or sets budget
  public double Budget
  {
    get { return _budget; }
    set { _budget = value; }
  }
}

 

این کلاس دارای ۳ Property با اسم های Name و Phone  و  Budget می باشد که امکان Set و Get شدن دارند.

 

کلاس بعدی کلاس ProspectMemory هستش که نقش Caretaker را دارد. و به صورت زیر پیاده سازی می شود.

class ProspectMemory
 {
   private Memento _memento;

   // Property
   public Memento Memento
   {
     set { _memento = value; }
     get { return _memento; }
   }
 }

 

این کلاس یک Property از نوع Memento دارد که امکان Set و Get شدن دارند.

و کلاس آخر ما کلاس SalesProspect هستش که نقش Originator را برعهده دارد.

class SalesProspect
 {
   private string _name;
   private string _phone;
   private double _budget;

   // Gets or sets name
   public string Name
   {
     get { return _name; }
     set
     {
       _name = value;
       Console.WriteLine("Name:  " + _name);
     }
   }

   // Gets or sets phone
   public string Phone
   {
     get { return _phone; }
     set
     {
       _phone = value;
       Console.WriteLine("Phone: " + _phone);
     }
   }

   // Gets or sets budget
   public double Budget
   {
     get { return _budget; }
     set
     {
       _budget = value;
       Console.WriteLine("Budget: " + _budget);
     }
   }

   // Stores memento
   public Memento SaveMemento()
   {
     Console.WriteLine("\nSaving state --\n");
     return new Memento(_name, _phone, _budget);
   }

   // Restores memento
   public void RestoreMemento(Memento memento)
   {
     Console.WriteLine("\nRestoring state --\n");
     this.Name = memento.Name;
     this.Phone = memento.Phone;
     this.Budget = memento.Budget;
   }
 }

 

در کلاس SalesProspect سه Property با نام های Name و Phone و Budget وجود دارد که امکان Set و Get شدن دارند.همچنین دو متد در این کلاس وجود دارد .متد اول ،متد SaveMemento می باشد که این متد با استفاده از مقادیر فعلی  Set شده در Property های این کلاس ، یک شی از کلاس Memento را بر می گرداند.متد بعدی ، متد RestoreMemento می باشد.این متد در پارامتر های ورودی خود ،یک پارامتر از نوع Memento دریافت کرده و حالت فعلی Property های این کلاس ما را به حالتی که Memento ورودی به این متد ،بر می گرداند.

حال به سراغ استفاده از کلاس های نوشته شده می رویم تا ببینیم این pattern از دید کلاینت به چه صورت باید استفاده شود.

class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    static void Main()
    {
      SalesProspect s = new SalesProspect();
      s.Name = "Noel van Halen";
      s.Phone = "(412) 256-0990";
      s.Budget = 25000.0;
 
      // Store internal state
      ProspectMemory m = new ProspectMemory();
      m.Memento = s.SaveMemento();
 
      // Continue changing originator
      s.Name = "Leo Welch";
      s.Phone = "(310) 209-7111";
      s.Budget = 1000000.0;
 
      // Restore saved state
      s.RestoreMemento(m.Memento);
 
      // Wait for user
      Console.ReadKey();
    }
  }

 

در این کلاس ابتدا یک شی از کلاس SalesPropspect ساخته ایم.این کلاس در حقیقت همان شی اصلی ما می باشد و نقش Originator را دارد و هدف ایجاد Checkpoint از این کلاس می باشد.ما شی را از این کلاس می سازیم و Property های آن را مقدار دهی می کنیم.حال می خواهیم یک Memento از حالت فعلی این شی ایجاد کنیم.ابتده یک شی از کلاس PropspectMemory ایجاد کرده .سپس با فرخوانی متد SaveMemento شی ما و ست کردن نتیجه در Proeprty Memento از کلاس ProspectMemory یک از Checkpoint از آبجکت را ذخیره می کنیم. حال مقادیر شی مان را تغییر میدهیم و در نهایت با استفاده از متد RestoreMemento ، مقادیر شی را به مقادیری که از آن یک CheckPoint  داشتیم بر می گردانیم.

در آخر باید بگم که این الگو ،جز الگوی های با کاربرد کم می باشد.

در مطلب بعدی الگوی طراحی Observer را با هم بررسی خواهیم کرد.

 

منبع این مطلب: http://www.dofactory.com/net/memento-design-pattern