Memento

GOF Intent:
Without violating encapsulation, capture and externalize an object’s internal state so that the object can be restored to this state later.

Memento Pattern براي نگهداري state يک Object جهت بازگرداندن آن به همان State از جمله هنگام Undo بکار مي رود.

کاربردهاي اين Pattern زياد است. هرجا که امکان Undo مورد نياز است يا در بازي ها که امکان بازگشت به مراحل قبل وجود دارد و غيره.

اين Pattern با عنوان Token نيز شناخته مي شود.

اين Pattern سه جزء دارد:

  • Originator عبارت است از Object اصلي که State آن بايد نگهداري شود.
  • Memento عبارت است از Object اي که State داخلي Originator را نگه مي داردو در واقع يک snapshot لحظه اي از Originator است.
  • Caretaker عبارت است از Object اي که State داخلي Originator را تغيير مي دهد و در صورت لزوم آن را Undo مي کند.
Caretaker هر زمان که لازم است از Originator درخواست يک memento مي کند که در آن State لحظه اي Originator نگهداري مي شود. Caretaker هنگام Undo دوباره memento را در اختيار Originator مي گذارد تا Originator با استفاده از آن خود را به آن State بازگرداند. همچنين caretaker نبايد بتواند هيچ تغييري روي memento ايجاد کند.

نمونه کد:

class Originator {
   private String state;

   public void set(String state) {
      System.out.println(“Originator: Setting state to ” + state);
      this.state = state;
   }

   public Memento saveToMemento() {
      System.out.println(“Originator: Saving to Memento.”);
      return new Memento(state);
   }

   public void restoreFromMemento(Memento memento) {
      state = memento.getSavedState();
      System.out.println(“Originator: State restoring from Memento: ” + state);
   }


   // Memento inner class
   public class Memento {
      private final String state;

   private Memento(String stateToSave) {
         state = stateToSave;
      }

      private String getSavedState() {
         return state;
      }
   }
}


class Caretaker {

   public static void main(String[] args) {
      List savedStates = new ArrayList();
      Originator originator = new Originator();

      originator.set(“State1″);
      originator.set(“State2″);
      savedStates.add(originator.saveToMemento());
      originator.set(“State3″);
      savedStates.add(originator.saveToMemento());
      originator.set(“State4″);

      originator.restoreFromMemento(savedStates.get(1));
   }
}

نکته:
در اين مثال state يک String ساده در نظر گرفته شده است. اما در حالت واقعي State اغلب يک Object است. در اين حالت براي ساخت memento از دستور Clone استفاده مي شود.

public class Memento {
   private final State state;

   private Memento(State stateToSave) {
      state = stateToSave.clone();
   }

   private Sate getSavedState() {
      return state;
   }
}

چند نکته:

  1. درصورتي که نياز باشد حجم اطلاعات زيادي در Memento نگهداري شود يا Caretaker به دفعات زياد memento را دريافت کند، اين کار مي تواند overhead زيادي روي سيستم داشته باشد و منابع سيستم را اشغال کند. يک راه حل براي اين مشکل اين است که تغييرات در memento بصورت incremental نگهداري شوند. يعني به جاي نگهداري کل state، فقط تغييرات انجام شده نسبت به State قبل نگهداري شود. اين کار البته مديريت حساب شده تري در ذخيره و بازيابي memento را مي طلبد.
  2. بايد تمام تمهيدات ممکن را انديشيد که حتي المقدور تنها Originator امکان تغيير memento را داشته باشد.
  3. وظيفه پاک کردن memento هايي که مورد استفاده قرار مي گيرند با Caretaker است. هرچند Caretaker اصولا ديدي از حجم data و state موجود در memento ندارد. با اين حال بي توجهي به پاک کردن memento ممکن است، حافظه زيادي را اشغال و بلا استفاده کند.



منبع ها:

  1. Design Patterns – Elements of Reusable Object Oriented Software (GOF) By Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides
  2. Memento Pattern in Wikipedia

پست شده در دسته‌بندی نشده

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

*


هفت − = 6

شما می‌توانید از این دستورات HTML استفاده کنید: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

تماس با من: admin@paspars.com