定義と構造
記念モードはトークンモードとも呼ばれます。 GOFはメモモードを次のように定義します。カプセル化を破壊することなく、オブジェクトの内部状態をキャプチャし、この状態をオブジェクトの外側に保存します。このようにして、オブジェクトは後で元の保存状態に復元できます。
コマンドモードについて話すとき、私たちはかつて、中間コマンドロールを使用すると、元に戻してやり直しの関数を実現できると述べました。定義から、メモモードはオブジェクトの履歴状態を保存するために特別に使用されていることがわかります。したがって、コマンドモードでは、メモモードと組み合わせて関数を元に戻して再装うことができます。
実際、特定の瞬間にオブジェクトの状態を保存する機能を実現することは非常に簡単です - オブジェクトに属性をバックアップ管理に特化したオブジェクトに保存し、必要に応じてバックアップ属性を元のオブジェクトに戻すために合意した方法を呼び出します。ただし、バックアップオブジェクトが元のオブジェクトのプロパティにアクセスできるようにするためによく見なければなりません。パッケージ内のオブジェクトの元のプライベートのプロパティをすべて開示する必要があることを意味しますか?アプローチがカプセル化を破った場合は、リファクタリングを検討する必要があります。
メモモードは、「特定の時間にオブジェクトの元の状態を回復する」という問題のためにGOFによって提案された一般的なソリューションにすぎません。したがって、言語特性などの要因により、カプセル化を維持する方法に関しては、覚書のパターンは詳細に説明されていませんが、C ++に基づくアイデアのみを説明します。
1)記念の役割:メモの役割は、「メモイニシエーターロール」の内部ステータスを保存します。 「覚書イニシエーターの役割」は、必要に応じて「覚書イニシエーターの役割」の内部状態が保存されるかを決定します。 「覚書イニシエーターの役割」以外の他のオブジェクトがメモにアクセスするのを防ぐため。メモには実際には2つのインターフェイスがあります。 「メモマネージャーの役割」は、メモによって提供される狭いインターフェイスのみを見ることができます。これは、メモロールに保存されている属性には見えません。 「覚書イニシエーターの役割」は、幅広いインターフェイスを見ることができます。メモの役割に入れた属性を取得できます。
2)メモ開始(オリジネーター)役割:「メモ開始の役割」は、現在の瞬間に内部状態を記録するメモを作成します。メモを使用して、必要に応じて内部状態を復元します。
3)メモマネージャー(世話人)の役割:メモの保存を担当します。メモのコンテンツを操作またはチェックすることはできません。
メモモードのクラス図は本当に簡単です:
一般的なコードの実装
class originator {private string state = ""; public string getState(){return state; } public void setState(string state){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(String state){this.state = state; } public string getState(){return state; } public void setState(string state){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( "Initial State:"+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()); }}コードは、単一の州の単一バックアップの例を示しています。ロジックは非常に単純です。Originatorクラスの状態変数は、必要に応じて復元できるようにバックアップする必要があります。 Mementoクラスでは、Originatorクラスに一時的な状態変数を保存するために使用される状態変数もあります。世話人クラスは、覚書クラスの管理に使用されます。メモクラスは、状態を書き込むか、状態を覚書オブジェクトに取得するために使用されます。
マルチステートマルチバックアップメモ
一般的なコードのデモンストレーションの例では、オリジネータークラスにはバックアップする必要がある状態変数が1つしかありませんが、通常、イニシエーターの役割は通常Javabeanであり、オブジェクトにバックアップする必要がある変数が複数あり、バックアップする必要がある複数の状態があります。これは、マルチステートマルチバックアップメモです。メモを実装するには多くの方法があります。メモには多くの変形と処理方法があります。一般的に一般的なコードのような方法は使用されません。ほとんどの場合、メモはマルチステートと複数のバックアップです。実際、マルチステートとマルチバックアップを実装することも非常に簡単です。最も一般的に使用される方法は、Memementoにマップコンテナを追加してすべての状態を保存し、世話人クラスのマップコンテナを使用してすべてのバックアップを保存することです。以下に、マルチステートとマルチバックアップの例を示します。
class originator {private string state1 = ""; private string state2 = ""; private string state3 = ""; public string 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.equalsignorecase( "class")){result.put(fieldname、fieldvalue); }}}} catch(Exception e){e.printstacktrace(); } return result; } public static void restoreProp(object bean、map <string、object> propmap){try {beaninfo beaninfo = introspector.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(String Index、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( "=== modified status ===/n"+ori); ori.restorememento(caretaker.getmemento( "001")); System.out.println( "===復元状態===/n"+ori); }}覚書モードの利点と短所、および該当するシナリオの覚書モードの利点は次のとおりです。
イニシエーターの役割のステータスが変更されると、間違った変更になる可能性があります。メモモードを使用して、この間違った変更を復元できます。
バックアップのステータスは、イニシエーターの役割の外側に保存されるため、イニシエーターの役割は各バックアップのステータスを管理する必要はありません。
メモモードの短所:
実際のアプリケーションでは、覚書モードはマルチステートおよびマルチバックアップです。イニシエーターの役割の状態は、比較的ひどくリソースを消費する覚書オブジェクトに保存する必要があります。
ロールバック操作を提供する必要がある場合、JDBCトランザクション操作、CTRL+Zテキストエディターの回復など、メモモードを使用することが非常に適しています。