Метафора
Представьте себе гардероб и гардеробщицу, когда вы сдаете свою одежду в гардероб, гардеробщица реализует паттерн «хранитель», запоминая ваше состояние — «одежду», когда вам потребуется восстановить состояние, вы просто обращаетесь к гардеробщице за одеждой и восстанавливаете свое состояние до прихода в гардероб.
Назначение
Паттерн позволяет, не нарушая инкапсуляцию, зафиксировать и сохранить внутреннее состояние объекта так, чтобы позднее восстановить его в это состояние.
Используется:
- В приложениях, где необходимо вести историю состояния объекта и при необходимости его восстанавливать (undo/redo операции в графических или текстовых редакторах); Обычно совместно с паттерном команда;
- В случае необходимости получения состояния объекта, не нарушая при этом его инкапсуляцию.
Диаграмма
Объекты:
- Originator – создатель, объект позволяющий зафиксировать своё состояние, представляемое в виде объекта Memento (это Вы из метафоры);
- Memento – состояние объекта Originator (Ваши вещи);
- Caretaker – хранитель состояния (Гардеробщица), который не должен изменять или читать состояние, а быть только его хранителем. Определение состояния и его чтение это исключительно обязанность создателя (Originator).
Состояние для примера представлено атрибутом типа String.
Пример
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
CLASS lcl_originator DEFINITION DEFERRED. CLASS lcl_momento DEFINITION FRIENDS lcl_originator. PUBLIC SECTION. METHODS: constructor IMPORTING iv_state TYPE string. PRIVATE SECTION. METHODS: get_state RETURNING VALUE(rv_state) TYPE string. DATA: mv_state TYPE string. ENDCLASS. CLASS lcl_momento IMPLEMENTATION. METHOD constructor. mv_state = iv_state. ENDMETHOD. METHOD get_state. rv_state = mv_state. ENDMETHOD. ENDCLASS. CLASS lcl_caretaker DEFINITION. PUBLIC SECTION. DATA: mo_state TYPE REF TO lcl_momento. ENDCLASS. CLASS lcl_originator DEFINITION. PUBLIC SECTION. METHODS: create_memento RETURNING VALUE(ro_memento) TYPE REF TO lcl_momento, set_memento IMPORTING io_memento TYPE REF TO lcl_momento, set_state IMPORTING iv_state TYPE string, get_state RETURNING VALUE(rv_state) TYPE string. PRIVATE SECTION. DATA: mv_state TYPE string. ENDCLASS. CLASS lcl_originator IMPLEMENTATION. METHOD set_state. mv_state = iv_state. ENDMETHOD. METHOD get_state. rv_state = mv_state. ENDMETHOD. METHOD set_memento. mv_state = io_memento->get_state( ). ENDMETHOD. METHOD create_memento. CREATE OBJECT ro_memento EXPORTING iv_state = mv_state. ENDMETHOD. ENDCLASS. START-OF-SELECTION. DATA: lo_originator TYPE REF TO lcl_originator, lo_caretaker TYPE REF TO lcl_caretaker, lv_state TYPE string. CREATE OBJECT lo_originator. lo_originator->set_state( 'ON' ). CREATE OBJECT lo_caretaker. lo_caretaker->mo_state = lo_originator->create_memento( ). lo_originator->set_state( 'OFF' ). lv_state = lo_originator->get_state( ). WRITE:/ lv_state. lo_originator->set_memento( lo_caretaker->mo_state ). lv_state = lo_originator->get_state( ). WRITE:/ lv_state. |
Благодаря концепции друзей, доступ к чтению Memento (вызов приватных методов) имеет только Originator.