In the book "Design mode: The basis of reusable object-oriented software" in Gof, the memo pattern is said to capture the internal state of an object without compromising encapsulation, and to save the state outside of that object. The object can then be restored to its previously saved state. Class diagrams and instances: A simple pattern instance:
#include <iostream>#include<string>using namespacestd;classMemento {Private: stringState ; Public: Memento () { state=""; } Memento (stringState ) { This->state =State ; } stringgetState () {returnState ; } voidSetState (stringState ) { This->state =State ; }};classOriginator {Private : stringState ; Public: Originator () { state=""; } stringgetState () {returnState ; } voidSetState (stringState ) { This->state =State ; } Memento Creatememento () {returnMemento ( This-State ); } voidRestorememento (Memento Memento) { This-setState (Memento.getstate ()); }};classCaretaker {Private: Memento Memento; Public: Memento Getmemento () {returnMemento; } voidSetmemento (Memento Memento) { This->memento =Memento; }};intMain (intargcChar*argv[]) {originator originator; Originator.setstate ("Status 1"); cout<<"Initial state:"<<originator.getstate () <<Endl; Caretaker caretaker; Caretaker.setmemento (Originator.creatememento ()); Originator.setstate ("Status 2"); cout<<"post-Change status:"<<originator.getstate () <<Endl; Originator.restorememento (Caretaker.getmemento ()); cout<<"post-Restore status:"<<originator.getstate () <<Endl;}
UML Class Diagram
Memento: Memo stores the internal state of the sender object. The source determines which internal states the memo stores as needed, and prevents access to the memo from objects other than the original. The memo actually has two interfaces, and the manager can only see the narrow interface of the memo ———— it can only pass the memo to other objects. Instead, the generator can see a wide interface that allows it to access all the data needed to return to the previous state. Ideally, only the original sender that generated the memo is allowed to access the internal state of this memo;
Originator: The generator creates a memo to record its internal state at the current moment; we use memos to restore the internal state;
Caretaker: Responsible for keeping the memo; However, the contents of the memo cannot be manipulated or checked.
The memo pattern is coordinated in the following ways:
The manager requests a memo from the sender, retains it for a period of time, sends it back to the original, and sometimes the manager does not return the memo to the original, because the sender may not need to go back to the previous state. The memo is passive, and only the original generator that created the memo assigns and retrieves its state, such as the following timing diagram:
#include <iostream>using namespacestd;structstate{wchar_t wcsstate[260];};classmemento{ Public: Memento ( State*pState): M_pstate (pState) {} State*getstate () {returnm_pstate;}Private: Friendclassoriginator; State*m_pstate;};classoriginator{ Public: Originator (): M_pstate (NULL) {}~originator () {//Delete The storage of the state if(m_pstate) {Deletem_pstate; M_pstate=NULL; } } voidSetmemento (Memento *Pmemento); Memento*Creatememento (); voidSetValue (wchar_t *value) {memset (Wcsvalue,0,260*sizeof(wchar_t)); wcscpy_s (Wcsvalue,260, value); } voidPrintstate () {wcout<<wcsvalue<<Endl;}Private: State*m_pstate;//To store the object ' s Statewchar_t wcsvalue[260];//This is the object ' s real data}; Memento*Originator::creatememento () {m_pstate=NewState ; if(M_pstate = =NULL) { returnNULL; } Memento*pmemento =NewMemento (m_pstate); wcscpy_s (M_pstate->wcsstate,260, Wcsvalue);//Backup The value returnPmemento;}voidOriginator::setmemento (Memento *Pmemento) {M_pstate= pmemento->GetState (); //Recovery the Datamemset (Wcsvalue,0,260*sizeof(wchar_t)); wcscpy_s (Wcsvalue,260, m_pstate->wcsstate);}//Manager the Mementoclasscaretaker{ Public: Memento*getmemento () {returnM_pmemento;} voidSetmemnto (Memento *Pmemento) { //Free the previous Memento if(m_pmemento) {DeleteM_pmemento; M_pmemento=NULL; } //Set the new MementoM_pmemento =Pmemento; }Private: Memento*M_pmemento;};intMain () {originator*poriginator =Neworiginator (); Poriginator->setvalue (L" on"); Poriginator-printstate (); //Now I backup the stateCaretaker *pcaretaker =Newcaretaker (); Pcaretaker->setmemnto (poriginator->Creatememento ()); //Set the new statePoriginator->setvalue (L"Off"); Poriginator-printstate (); //Recovery to the old statePoriginator->setmemento (pcaretaker->Getmemento ()); Poriginator-printstate (); if(pcaretaker) {DeletePcaretaker; } if(poriginator) {DeletePoriginator; } return 0;}
Applicability:
For classes that are more complex, but need to record or maintain attribute history, or if you need to save a property that is only a small fraction of many properties, originator can revert to the previous state based on the saved memo.
Advantages and Disadvantages
Advantages:
1) When the status of the initiator is changed, there may be a mistake, and we can use the memo mode to restore the error.
2) The status of the backup is stored outside the initiator role, so that the initiator role does not need to manage the status of each backup.
Disadvantages:
1) If the backed-up object has a large amount of information or is created and restored very frequently, it can cause significant performance overhead.
[Design mode] Memo mode memento pattern