stringtranslate.com

Модель «памяти»

Шаблон memento — это шаблон проектирования программного обеспечения , который раскрывает частное внутреннее состояние объекта. Один из примеров того, как это можно использовать, — это восстановление объекта в его предыдущее состояние (откат через откат), другой — управление версиями, третий — пользовательская сериализация.

Шаблон memento реализуется с тремя объектами: originator , a caretaker и a memento . Originator — это некоторый объект, имеющий внутреннее состояние. Смотритель собирается что-то сделать с originator, но хочет иметь возможность отменить изменение. Смотритель сначала запрашивает у originator объект memento. Затем он выполняет любую операцию (или последовательность операций), которую он собирался выполнить. Чтобы вернуться к состоянию до операций, он возвращает объект memento originator. Сам объект memento является непрозрачным объектом (который хранитель не может или не должен изменять). При использовании этого шаблона следует соблюдать осторожность, если originator может изменять другие объекты или ресурсы — шаблон memento работает с одним объектом.

Классические примеры шаблона «памяти» включают генератор псевдослучайных чисел (каждый потребитель PRNG выступает в роли смотрителя, который может инициализировать PRNG (создателя) тем же самым начальным числом (памятью) для создания идентичной последовательности псевдослучайных чисел) и состояние в конечном автомате.

Структура

Диаграмма классов и последовательностей UML

Пример класса UML и диаграммы последовательности для шаблона проектирования Memento. [1]

В приведенной выше диаграмме классов UML Caretakerкласс ссылается на Originatorкласс для сохранения ( createMemento()) и восстановления ( restore(memento)) внутреннего состояния оригинатора.
Класс Originatorреализует
(1) createMemento()путем создания и возврата Mementoобъекта, который хранит текущее внутреннее состояние оригинатора, и
(2) restore(memento)путем восстановления состояния из переданного Mementoобъекта.

Диаграмма последовательности UML показывает взаимодействия во время выполнения:
(1) Сохранение внутреннего состояния инициатора: Caretakerобъект вызывает createMemento()объект Originator, который создает Mementoобъект, сохраняет его текущее внутреннее состояние ( setState()) и возвращает Mementoв Caretaker.
(2) Восстановление внутреннего состояния инициатора: Caretakerвызывает restore(memento)объект Originatorи указывает Mementoобъект, который хранит состояние, которое должно быть восстановлено. Originatorполучает состояние ( getState()) из , Mementoчтобы установить свое собственное состояние.

Пример Java

Следующая программа на Java иллюстрирует использование шаблона «отменить».

import java.util.List ; import java.util.ArrayList ; class Originator { private String state ; // Класс также может содержать дополнительные данные, которые не являются частью // состояния , сохраненного в memento.. public void set ( String state ) { this.state = state ; System.out.println ( "Originator: Установка состояния в " + state ); } public Memento saveToMemento ( ) { System.out.println ( " Originator : Сохранение в Memento." ) ; return new Memento ( this.state ) ; } public void restoreFromMemento ( Memento memento ) { this.state = memento.getSavedState ( ) ; System.out.println ( " Originator : Состояние после восстановления из Memento: " + state ) ; } public static class Memento { private final String state ;                                                        public Memento ( String stateToSave ) { state = stateToSave ; } // доступно только внешнему классу private String getSavedState () { return state ; } } } class Caretaker { public static void main ( String [] args ) { List < Originator.Memento > savedStates = new ArrayList < Originator.Memento > (); Originator originator = new Originator ( ); originator.set ( "State1" ) ; originator.set ( " State2" ); savedStates.add ( originator.saveToMemento ( ) ) ; originator.set ( " State3" ) ; // Мы можем запросить несколько mementos и выбрать , к какому из них вернуться. savedStates.add ( originator.saveToMemento ( ) ); originator.set ( " State4" ) ; originator.restoreFromMemento ( savedStates.get ( 1 ) ) ; } }                                                

Вывод:

Инициатор: Установка состояния в State1Инициатор: Установка состояния в State2Создатель: Сохранение в Memento.Инициатор: Установка состояния в State3Создатель: Сохранение в Memento.Инициатор: Установка состояния в State4Создатель: Состояние после восстановления из Memento: Состояние3

В этом примере в качестве состояния используется String, который является неизменяемым объектом в Java. В реальных сценариях состояние почти всегда будет изменяемыми объектами, и в этом случае необходимо сделать копию состояния.

Надо сказать, что показанная реализация имеет недостаток: она объявляет внутренний класс. Было бы лучше, если бы эта стратегия memento могла применяться к более чем одному создателю.

Есть еще три основных способа получить Memento:

  1. Сериализация.
  2. Класс, объявленный в том же пакете.
  3. Доступ к объекту также возможен через прокси-сервер, который может выполнять любые операции сохранения/восстановления объекта.

Пример на С#

Шаблон memento позволяет захватить внутреннее состояние объекта, не нарушая инкапсуляцию, так что позже можно отменить/вернуть изменения, если это необходимо. Здесь можно увидеть, что объект memento фактически используется для отмены изменений, сделанных в объекте.

класс Memento { частная строка только для чтения сохраненное состояние ;      частный Memento ( string stateToSave ) { savedState = stateToSave ; }        public class Originator { private string state ; // Класс также может содержать дополнительные данные, которые не являются частью // состояния, сохраненного в памяти.         public void Set ( string state ) { Console.WriteLine ( " Оригинатор : Установка состояния на " + state ) ; this.state = state ; }            public Memento SaveToMemento () { Console.WriteLine ( " Originator : Save to Memento." ); return new Memento ( state ) ; }         public void RestoreFromMemento ( Memento memento ) { state = memento . savedState ; Console . WriteLine ( "Originator: Состояние после восстановления из Memento: " + state ); } } }            класс Смотритель { static void Main ( string [] args ) { var savedStates = new List < Memento > ();            var originator = new Memento.Originator ( ) ; originator.Set ( "State1" ) ; originator.Set ( " State2" ) ; savedStates.Add ( originator.SaveToMemento ( ) ); originator.Set ( " State3" ); // Мы можем запросить несколько mementos и выбрать , к какому из них выполнить откат. savedStates.Add ( originator.SaveToMemento ( )); originator.Set ( " State4 " ) ;            originator.RestoreFromMemento ( savedStates [ 1 ] ) ; } } 

Пример на Python

""" Пример шаблона Memento. """Класс  Создатель :  _state  =  "" def  set ( self ,  state :  str )  ->  None :  print ( f " Оригинатор : Установка состояния в { state } " )  self._state = state   def  save_to_memento ( self )  - >  " Memento " :  return  self.Memento ( self._state ) def  restore_from_memento ( self ,  m :  " Memento" ) -  >  None :  self._state = m.get_saved_state ( ) print ( f " Создатель : Состояние после восстановления из Memento : { self._state } " )    класс  Мементо : def  __init__ ( self ,  state ):  self . _state  =  state def  get_saved_state ( self ):  вернуть  self . _stateсохраненные_состояния  =  [ ] создатель  =  Создатель ( ) создатель.установить ( " Состояние1 " ) создатель.установить ( " Состояние2 " ) сохраненные_состояния.добавить ( создатель.сохранить_в_память ( ) )originator.set ( " State3 " ) saved_states.append ( originator.save_to_memento ( ) )создатель . set ( "State4" )originator . restore_from_memento ( сохраненные_состояния [ 1 ])

Пример JavaScript

// Шаблон Memento используется для сохранения и восстановления состояния объекта. // Memento — это снимок состояния объекта. var Memento = { // Пространство имен: Memento savedState : null , // Сохраненное состояние объекта.        save : function ( state ) { // Сохранение состояния объекта. this . savedState = state ; },         restore : function () { // Восстановить состояние объекта. return this . savedState ; } };       // Originator — это объект, который создает мементо. // определяет метод сохранения состояния внутри мементо. var Originator = { // Пространство имен: Состояние создателя : null , // Состояние, которое необходимо сохранить        // Создает нового создателя с начальным состоянием null createMemento : function () { return { state : this . state // Состояние копируется в memento. }; }, setMemento : function ( memento ) { // Устанавливает состояние создателя из memento this . state = memento . state ; } };                       // Caretaker хранит памятные вещи объектов и // предоставляет операции для их извлечения. var Caretaker = { // Пространство имен: Mementos Caretaker : [], // Памятные вещи объектов. addMemento : function ( memento ) { // Добавить памятную вещь в коллекцию. this . mementos . push ( memento ); }, getMemento : function ( index ) { // Получить памятную вещь из коллекции. return this . mementos [ index ]; } };                       var action_step = "Foo" ; // Действие, которое должно быть выполнено/состояние объекта, которое должно быть сохранено. var action_step_2 = "Bar" ; // Действие, которое должно быть выполнено/состояние объекта, которое должно быть сохранено.        // установить начальное состояние Originator.state = action_step ; Caretaker.addMemento ( Originator.createMemento ( )); // сохранить состояние в истории console.log ( " Начальное состояние: " + Originator.state ) ; // Foo     // изменить состояние Originator.state = action_step_2 ; Caretaker.addMemento ( Originator.createMemento ()); // сохранить состояние в истории console.log ( " Состояние после изменения: " + Originator.state ) ; // Bar      // восстановить первое состояние - отменить Originator.setMemento ( Caretaker.getMemento ( 0 ) ); console.log ( " Состояние после отмены : " + Originator.state ) ; // Foo   // восстановить второе состояние - повтор Originator.setMemento ( Caretaker.getMemento ( 1 ) ) ; console.log ( " Состояние после повтора: " + Originator.state ) ; // Bar   

Ссылки

  1. ^ "Шаблон дизайна Memento - Структура и сотрудничество". w3sDesign.com . Получено 2017-08-12 .

Внешние ссылки