메멘토 패턴

Memento pattern

메멘토 패턴은 롤백을 통해 개체를 이전 상태로 복원하는 기능을 제공하는 소프트웨어 설계 패턴이다.

메멘토 패턴은 발신인, 관리인, 메멘토의 세 가지 객체로 구현된다.원조는 내부 상태를 가진 어떤 물체다.관리인이 원생에게 무슨 짓을 하려고 하지만, 그 변화를 되돌릴 수 있기를 원한다.관리인은 먼저 발신인에게 미멘토 물건을 요구한다.그리고 나서 그것은 그것이 하려던 모든 작전(또는 일련의 작전)을 수행한다.작업 전 상태로 롤백하려면, memento 객체를 원점자에게 반환한다.메멘토 물체 자체는 불투명한 물체(관리자가 변경할 수 없거나 변경할 수 없는 물체)이다.이 패턴을 사용할 때, 발신자가 다른 물체나 자원을 변경할 수 있는 경우 주의해야 한다. 즉, 메멘토 패턴은 단일 물체에 작용한다.

메멘토 패턴의 고전적인 예로는 유사란돔 번호 생성기(PRNG의 각 소비자는 동일한 시드(메멘토)로 PRNG(원시자)를 초기화하여 동일한 수의 시퀀스를 생산할 수 있는 관리자로서의 역할을 한다)와 유한 상태 기계에서의 상태를 들 수 있다.

개요

메멘토 디자인 패턴은 유연하고 재사용 가능한 객체 지향 소프트웨어, 즉 구현, 변경, 테스트, 재사용하기 쉬운 객체를 설계하기 위해 반복적인 설계 문제를 해결하는 방법을 설명하는 23가지 GoF 디자인 패턴 중 하나이다.메멘토 패턴은 초기 HP 제품을 위해 노아 톰슨, 데이비드 에스피리투, 드류 클링켄비어드 박사가 만들었다.

메멘토 디자인 패턴이 해결할 수 있는 문제는 무엇인가?

[2]

  • 객체의 내부 상태는 객체를 나중에 이 상태로 복원할 수 있도록 외부에 저장해야 한다.
  • 물체의 캡슐화를 위반해서는 안 된다.

문제는 잘 설계된 물체가 캡슐화되어 그 표현(데이터 구조)이 물체 내부에 숨겨져 물체 외부에서 접근할 수 없다는 점이다.

메멘토 디자인 패턴은 어떤 솔루션을 설명하고 있는가?

객체(원본 작성자) 자신이 책임지도록 설정

  • (메모) 객체에 내부 상태 저장 및
  • (메모) 개체에서 이전 상태로 복원.

미멘토를 만든 발신자만이 그것에 접근할 수 있다.

의뢰인(담배업자)은 발신인에게 미멘토를 요청(발송인의 내부 상태를 저장하기 위해)하고, 미멘토를 발신인에게 다시 전달(이전 상태로 복원하기 위해)할 수 있다.

이것은 발신자의 캡슐화를 위반하지 않고 발신자의 내부 상태를 저장 및 복원할 수 있다.

아래 UML 클래스 및 시퀀스 다이어그램을 참조하십시오.

구조

UML 클래스 및 시퀀스 다이어그램

Memento 설계 패턴에 대한 샘플 UML 클래스 및 시퀀스 다이어그램.[3]

위의 UML클래스 다이어그램에서Caretakerclass는 다음을 가리킨다.Originator저장 클래스(createMemento()) 및 복원(restore(memento)) 발신자의 내부 상태.
Originator수업용구
(1)createMemento()생성 및 반환Memento발신자의 현재 내부 상태를 저장하는 개체
(2)restore(memento)과거로부터 상태를 복원하여Memento이의를 제기하다

UMLsequence 다이어그램은 런타임 교호작용을 보여준다.
(1) 발신자의 내부상태 저장:Caretaker반대 전화createMemento()에서Originator물체, 이 물체가 생성된다.Memento객체, 현재 내부 상태 저장(setState()) 및 반환Memento에게Caretaker.
(2) 발신자의 내부상태 복원:Caretaker전화를 하다restore(memento)에서Originator객체 및 지정Memento복원해야 하는 상태를 저장하는 개체.Originator상태 파악(getState()~에서Memento자신의 입장을 정하기 위해서.

자바 예제

다음 자바 프로그램은 미멘토 패턴의 "undo" 사용을 보여준다.

수입하다 java.util.리스트; 수입하다 java.util.배열 목록; 계급 기원자 {     사유의  ;     // 클래스에 다음 항목에 속하지 않는 추가 데이터가 포함될 수도 있음     // memento에 저장된 상태..       공중의 공허하게 하다 세트( ) {         . = ;         시스템.밖으로.인쇄하다("출발자:상태를 "로 설정하는 중 + );     }       공중의 메멘토 saveToMemento() {         시스템.밖으로.인쇄하다("기원:메멘토에 저장.");         돌아오다 새로운 메멘토(.);     }       공중의 공허하게 하다 restoreFromMemento(메멘토 메멘토) {         . = 메멘토.GetSavedState();         시스템.밖으로.인쇄하다("출발자:메멘토에서 복원 후 상태: " + );     }       공중의 정태의 계급 메멘토 {         사유의 최종의  ;          공중의 메멘토( stateToSave) {              = stateToSave;         }           // 외부 클래스만 액세스할 수 있음         사유의  GetSavedState() {             돌아오다 ;         }     } }   계급 관리인 {     공중의 정태의 공허하게 하다 본래의([] 아그) {         리스트<기원자.메멘토> savedStates = 새로운 배열 목록<기원자.메멘토>();           기원자 기원자 = 새로운 기원자();         기원자.세트("상태1");         기원자.세트("상태2");         savedStates.덧셈을(기원자.saveToMemento());         기원자.세트("상태3");         // 여러 개의 기념품을 요청할 수 있고, 어떤 기념품으로 돌아갈지 선택할 수 있다.         savedStates.덧셈을(기원자.saveToMemento());         기원자.세트("스테이트4");           기원자.restoreFromMemento(savedStates.얻다(1));        } } 

출력:

발신자:State1 Originator로 상태 설정:State2 Originator로 상태 설정: Memento에 저장발신자:State3 Originator로 상태 설정: Memento에 저장발신자:State4 Originator로 상태 설정:메멘토에서 복원 후 상태:상태3

이 예는 Java에서 불변의 객체인 String을 state로 사용한다.실제상황 시나리오에서 국가는 거의 항상 변이 가능한 물체가 될 것이며, 이 경우 국가의 복사본이 만들어져야 한다.

표시된 구현에는 단점이 있다고 말해야 한다: 내부 계층을 선언한다는 것이다.이 메멘토 전략을 둘 이상의 발신자에게 적용할 수 있다면 더 좋을 것이다.

메멘토를 달성하는 다른 방법에는 주로 세 가지가 있다.

  1. 연재.
  2. 동일한 패키지로 선언된 클래스.
  3. 또한 객체에 대한 저장/복원 작업을 수행할 수 있는 프록시를 통해 객체에 액세스할 수 있다.

C# 예제

메멘토 패턴은 캡슐화를 위반하지 않고 물체의 내부 상태를 캡처할 수 있도록 하여 나중에 필요할 경우 변경 사항을 취소/반복할 수 있다.여기서 메멘토 객체가 실제로 객체의 변경사항을 되돌리기 위해 사용된다는 것을 알 수 있다.

계급 메멘토 {     사유의 읽기 전용 끈을 매다 savedState;      사유의 메멘토(끈을 매다 stateToSave)     {         savedState = stateToSave;     }      공중의 계급 기원자     {         사유의 끈을 매다 ;         // 클래스에 다음 항목에 속하지 않는 추가 데이터가 포함될 수도 있음         // memento에 저장된 상태.          공중의 공허하게 하다 세트(끈을 매다 )         {             콘솔.WriteLine("출발자:상태를 "로 설정하는 중 + );             . = ;         }          공중의 메멘토 세이브토메멘토()         {             콘솔.WriteLine("기원:메멘토에 저장.");             돌아오다 새로운 메멘토();         }          공중의 공허하게 하다 RestoreFromMemento(메멘토 메멘토)         {              = 메멘토.savedState;             콘솔.WriteLine("출발자:메멘토에서 복원 후 상태: " + );         }     } }  계급 관리인 {     정태의 공허하게 하다 메인(끈을 매다[] 아그)     {         리스트<메멘토> savedStates = 새로운 리스트<메멘토>();          메멘토.기원자 기원자 = 새로운 메멘토.기원자();         기원자.세트("상태1");         기원자.세트("상태2");         savedStates.추가하다(기원자.세이브토메멘토());         기원자.세트("상태3");         // 여러 개의 기념품을 요청할 수 있고, 어떤 기념품으로 돌아갈지 선택할 수 있다.         savedStates.추가하다(기원자.세이브토메멘토());         기원자.세트("스테이트4");          기원자.RestoreFromMemento(savedStates[1]);     } } 

파이톤 예

""" 메멘토 패턴 예시. """   계급 메멘토:     반항하다 __init___(자아의, ) -> 없음:         자아의._국가 =       반항하다 get_properties_state(자아의):         돌아오다 자아의._국가   계급 기원자:     _국가 = ""      반항하다 세트(자아의, ) -> 없음:         인쇄하다("출발자:상태를 "로 설정하는 중, )         자아의._국가 =       반항하다 save_to_memento(자아의) -> 메멘토:         인쇄하다("기원:메멘토에 저장.")         돌아오다 메멘토(자아의._국가)      반항하다 restore_from_memento(자아의, 메멘토) -> 없음:         자아의._국가 = 메멘토.get_properties_state()         인쇄하다("출발자:메멘토에서 복원 후 상태: ", 자아의._국가)   saved_message = [] 기원자 = 기원자() 기원자.세트("상태1") 기원자.세트("상태2") saved_message.덧셈을(기원자.save_to_memento())  기원자.세트("상태3") saved_message.덧셈을(기원자.save_to_memento())  기원자.세트("스테이트4")  기원자.restore_from_memento(saved_message[1]) 

참조

  1. ^ Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison Wesley. pp. 283ff. ISBN 0-201-63361-2.{{cite book}}: CS1 maint : 복수이름 : 작성자 목록(링크)
  2. ^ "The Memento design pattern - Problem, Solution, and Applicability". w3sDesign.com. Retrieved 2017-08-12.
  3. ^ "The Memento design pattern - Structure and Collaboration". w3sDesign.com. Retrieved 2017-08-12.

외부 링크