Поведенческие паттерны: Хранитель (Memento) C#

Поведенческие паттерны:  Хранитель (Memento) C#

Назначение:

Паттерн Хранитель (Memento) — позволяет выносить внутреннее состояние объекта за его пределы для последующего возможного восстановления объекта без нарушения принципа инкапсуляции.

  • Не нарушая инкапсуляции, паттерн Memento получает и сохраняет за пределами объекта его внутреннее состояние так, чтобы позже можно было восстановить объект в таком же состоянии.
  • Является средством для инкапсуляции "контрольных точек" программы.
  • Паттерн Memento придает операциям "Отмена" (undo) или "Откат" (rollback) статус "полноценного объекта".

Когда использовать Memento?

  • Когда нужно сохранить состояние объекта для возможного последующего восстановления;

  • Когда сохранение состояния должно проходить без нарушения принципа инкапсуляции;

UML схема паттерна Хранитель​:

 UML схема паттерна Хранитель​

Участники

  • Memento: хранитель, который сохраняет состояние объекта Originator и предоставляет полный доступ только этому объекту Originator

  • Originator: создает объект хранителя для сохранения своего состояния

  • Caretaker: выполняет только функцию хранения объекта Memento, в то же время у него нет полного доступа к хранителю и никаких других операций над хранителем, кроме собственно сохранения, он не производит

Схема использования паттерна memento из реальной жизни:

хранитель пример из реальной жизни

Реализация Поведенческого шаблона "Memento" на C#


  class MainApp
  {
    
    static void Main()
    {
      Originator o = new Originator();
      o.State = "On";
 
      // Store internal state

      Caretaker c = new Caretaker();
      c.Memento = o.CreateMemento();
 
      // Continue changing originator

      o.State = "Off";
 
      // Restore saved state

      o.SetMemento(c.Memento);
 
      // Wait for user

      Console.ReadKey();
    }
  }
 
  /// <summary>

  /// The 'Originator' class

  /// </summary>

  class Originator

  {
    private string _state;
 
    // Property

    public string State
    {
      get { return _state; }
      set

      {
        _state = value;
        Console.WriteLine("State = " + _state);
      }
    }
 
    // Creates memento 

    public Memento CreateMemento()
    {
      return (new Memento(_state));
    }
 
    // Restores original state

    public void SetMemento(Memento memento)
    {
      Console.WriteLine("Restoring state...");
      State = memento.State;
    }
  }
 
  /// <summary>

  /// The 'Memento' class

  /// </summary>

  class Memento

  {
    private string _state;
 
    // Constructor

    public Memento(string state)
    {
      this._state = state;
    }
 
    // Gets or sets state

    public string State
    {
      get { return _state; }
    }
  }
 
  /// <summary>

  /// The 'Caretaker' class

  /// </summary>

  class Caretaker

  {
    private Memento _memento;
 
    // Gets or sets memento

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

Output 

State = On
State = Off
Restoring state:
State = On

Преимущества и недостатки хранителя

Преимущества Memento:

  •  Не нарушает инкапсуляции исходного объекта.
  •  Упрощает структуру исходного объекта. Ему не нужно хранить историю версий своего состояния.

 Недостатки Memento:

  •  Требует много памяти, если клиенты слишком часто создают снимки.
  •  Может повлечь дополнительные издержки памяти, если объекты, хранящие историю, не освобождают ресурсы, занятые устаревшими снимками.
  •  В некоторых языках программирования (таких как  PHP, Python, JavaScript и др) сложно гарантировать, чтобы только исходный объект имел доступ к состоянию снимка.

 

0 1.6K 16.12.2017 22:14

Комментарии:

Пожалуйста авторизируйтесь, чтобы получить возможность оставлять комментарии