정의와 구조
Memento 모드는 토큰 모드라고도합니다. GOF는 메모 모드를 다음과 같이 정의합니다. 캡슐화를 파괴하지 않고 객체의 내부 상태를 캡처 하고이 상태를 객체 외부에 저장하십시오. 이런 식으로 객체는 나중에 원래 저장 상태로 복원 할 수 있습니다.
명령 모드에 대해 이야기 할 때, 우리는 중간 명령 역할을 사용하면 실행 취소 및 Redo의 기능을 실현할 수 있다고 언급했습니다. 정의에서, 우리는 메모 모드가 구체적으로 객체의 과거 상태를 저장하는 데 사용되는 것을 알 수 있습니다. 따라서 명령 모드에서는 메모 모드와 함께 실행 취소 및 레디 기능을 구현할 수 있습니다.
실제로, 특정 순간에 객체의 상태를 저장하는 기능 만 인식하는 것은 여전히 매우 간단합니다. 속성을 객체에 저장하여 백업 관리를 전문으로하는 객체에 저장하고 합의 된 메소드를 호출하여 백업 속성을 필요할 때 원래 객체에 다시 넣습니다. 그러나 백업 오브젝트가 원래 오브젝트의 속성에 액세스 할 수 있도록 잘 살펴 봐야합니다. 패키지의 원래 비공개 특성의 모든 속성을 공개해야한다는 의미입니까? 접근 방식이 캡슐화를 중단 한 경우 리팩토링을 고려해야합니다.
각서 모드는 "특정 시간에 물체의 원래 상태를 복구하는"문제에 대해 GOF가 제안한 일반적인 솔루션 일뿐입니다. 따라서 언어 특성과 같은 요소로 인해 캡슐화를 유지하는 방법의 관점에서 각서 패턴은 자세히 설명되지 않고 C ++를 기반으로 한 아이디어 만 설명합니다.
1) Memorandum 역할은 "각서 개시자 역할"의 내부 상태를 저장합니다. "각서 개시자 역할"은 필요에 따라 "각서 개시자 역할"의 내부 상태를 결정합니다. "각서 개시자 역할"이외의 다른 객체가 메모에 액세스하는 것을 방지합니다. 메모에는 실제로 두 개의 인터페이스가 있습니다. "메모 관리자 역할"은 메모에서 제공하는 좁은 인터페이스 만 볼 수 있습니다. 메모 역할에 저장된 속성에는 보이지 않습니다. "각서 개시자 역할"은 광범위한 인터페이스를 볼 수 있습니다. 각서 역할에 넣는 속성을 얻을 수 있습니다.
2) 메모 개시 (원래) 역할 : "메모 시작 역할"은 현재 순간에 내부 상태를 기록하기위한 메모를 만듭니다. 필요할 때 내부 상태를 복원하기 위해 메모를 사용하십시오.
3) 각서 관리자 (관리자) 역할 : 메모 저장을 담당합니다. 메모의 내용은 작동하거나 확인할 수 없습니다.
메모 모드의 클래스 다이어그램은 정말 간단합니다.
일반 코드 구현
클래스 독창적 인 {private String state = ""; 공개 문자열 getState () {return state; } public void setstate (문자열 상태) {this.state = state; } public memento creatememento () {return new Memento (this.state); } public void restorememento (memento memento) {this.setstate (memento.getState ()); }} class memento {private String state = ""; public memento (문자열 상태) {this.state = state; } public String getState () {return state; } public void setstate (문자열 상태) {this.state = state; }} Class Caretaker {private memento memento; public memento getmemento () {return memento; } public void setmemento (memento memento) {this.memento = memento; }} public class client {public static void main (String [] args) {originator originator = new originator (); originator.setstate ( "상태 1"); System.out.println ( "초기 상태 :"+originator.getState ()); 관리인 간병인 = New Caretaker (); Caretaker.setmemento (originator.creatememento ()); originator.setstate ( "status2"); System.out.println ( "변경 후 상태 :"+originator.getState ()); originator.restorememento (caretaker.getmemento ()); System.out.println ( "복구 후 상태 :"+originator.getState ()); }}코드는 단일 상태 단일 백업의 예를 보여줍니다. 논리는 매우 간단합니다. 원시 클래스의 상태 변수는 필요할 때 복원 할 수 있도록 백업해야합니다. Memento 클래스에는 창시자 클래스에 상태 변수의 임시 상태를 저장하는 데 사용되는 상태 변수도 있습니다. 관리인 클래스는 각서 클래스를 관리하는 데 사용되며, 이는 상태를 작성하거나 각서 대상으로 상태를 검색하는 데 사용됩니다.
멀티 스테이트 멀티 백 up up-backup 메모
일반 코드 데모의 예에서, 원래 코드 클래스에는 백업이 필요한 단 하나의 상태 변수 만 가지고 있지만, 일반적으로 개시 자 역할은 일반적으로 Javabean이며, 개체에 백업 해야하는 둘 이상의 변수가 있으며, 백업 해야하는 하나 이상의 상태가 있습니다. 이것은 멀티 스테이트 멀티 백 up up-backup 메모입니다. 메모를 구현하는 방법에는 여러 가지가 있습니다. 메모에는 많은 변형 및 처리 방법이 있습니다. 일반 코드와 같은 방법은 일반적으로 사용되지 않습니다. 대부분의 경우 메모는 다중 상태 및 여러 백업입니다. 실제로 멀티 스테이트 및 멀티 백업을 구현하는 것은 매우 간단합니다. 가장 일반적으로 사용되는 방법은 Memento에 맵 컨테이너를 추가하여 모든 상태를 저장하고 관리자 클래스의 맵 컨테이너를 사용하여 모든 백업을 저장하는 것입니다. 아래에서 우리는 다중 주 및 멀티 백 up의 예를 제공합니다.
클래스 원문자 {private String State1 = ""; 개인 문자열 state2 = ""; 개인 문자열 state3 = ""; 공개 문자열 getState1 () {return state1; } public void setstate1 (String State1) {this.state1 = state1; } public String getState2 () {return state2; } public void setstate2 (String State2) {this.state2 = state2; } public String getState3 () {return state3; } public void setstate3 (String State3) {this.state3 = state3; } public memento creatememento () {return new memento (beanutils.backupprop (this)); } public void restorememento (memento memento) {beanutils.restoreprop (this, memento.getStatemap ()); } public String toString () {return "state1 ="+state1+"state2 ="+state2+"state3 ="+state3; }} class memento {private map <string, object> statemap; public memento (map <string, object> map) {this.statemap = map; } public map <string, object> getStatemap () {return Statemap; } public void setStatemap (map <string, object> statemap) {this.statemap = statemap; }} class beanutils {public static map <string, object> backupprop (object bean) {map <string, object> result = new Hashmap <String, Object> (); try {beaninfo beaninfo = introspector.getBeanInfo (bean.getClass ()); PropertyDescriptor [] descriptors = beanInfo.getPropertyDescriptors (); for (propertyDescriptor des : descriptors) {String fieldName = des.getName (); 메소드 getter = des.getReadMethod (); Object FieldValue = getter.invoke (Bean, New Object [] {}); if (! fieldName.equalSeignoreCase ( "class")) {result.put (fieldName, FieldValue); }}}} catch (예외 e) {e.printstacktrace (); } 반환 결과; } public static void restoreProp (Object Bean, Map <String, Object> propMap) {try {beanInfo beanInfo = introstector.getBeanInfo (bean.getClass ()); PropertyDescriptor [] descriptors = beanInfo.getPropertyDescriptors (); for (propertyDescriptor des : descriptors) {String fieldName = des.getName (); if (propmap.containskey (FieldName)) {method setter = des.getWritemEthod (); setter.invoke (bean, new Object [] {propmap.get (fieldName)}); }}} catch (예외 e) {e.printstacktrace (); }}} class Caretaker {private map <string, memento> memmap = new Hashmap <String, memento> (); public memento getmemento (String Index) {return memmap.get (index); } public void setmemento (문자열 색인, memento memento) {this.memmap.put (index, memento); }} class client {public static void main (String [] args) {originator ori = new originator (); 관리인 간병인 = New Caretaker (); ori.setstate1 ( "중국"); ori.setstate2 ( "strong"); ori.setstate3 ( "번영"); System.out.println ( "=== 초기화 상태 ===/n"+ORI); Caretaker.setmemento ( "001", ori.creatememento ()); ori.setstate1 ( "소프트웨어"); ori.setstate2 ( "구조"); ori.setstate3 ( "우수"); System.out.println ( "=== 수정 된 상태 ===/n"+ori); ori.restorememento (caretaker.getmemento ( "001")); System.out.println ( "=== 복원 된 상태 ===/n"+ori); }} 해당 시나리오에 대한 각서 모드의 장단점과 각서 모드의 장점은 다음과 같습니다.
개시 자 역할의 상태가 변경되면 잘못된 변화 일 수 있습니다. 메모 모드를 사용 하여이 잘못된 변경을 복원 할 수 있습니다.
백업의 상태는 개시 자 역할 외부에서 저장되므로 개시 자 역할은 각 백업의 상태를 관리 할 필요가 없습니다.
메모 모드의 단점 :
실제 애플리케이션에서 각서 모드는 다중 상태 및 다중 백업입니다. 개시 자 역할의 상태는 메모 대상에 저장되어야하며, 이는 자원을 상대적으로 심각하게 소비합니다.
롤백 작업을 제공 해야하는 경우 JDBC 트랜잭션 작업, CTRL+Z 텍스트 편집기의 복구 등과 같은 메모 모드를 사용하는 것이 매우 적합합니다.