Objective
And to the end of the year, also quiet heart to write code, we are very impetuous, turn out the classic "Paladin" play for a while, and play Big Boss, first save the file bar. This is my habit, before playing Big Boss, have to save a file, if won, and then save a file, cover before, if lost, restore the previous archive, then again. I think that's how we all play it. Oh, it's always a hit. OK, no, but the game's archive behavior fascinates me, how does it happen? With a curious heart, went to Baidu a bit; Oh, that's it. OK, let's start today's summary-memo mode.
Memo Mode
In Gof's "design pattern: The basics of reusable object-oriented software," the memo pattern is said to capture the internal state of an object without damaging the encapsulation, and to save the state outside the object. The object can then be restored to its previously saved state.
It is sometimes necessary to record the internal state of an object. To allow users to undo an indeterminate operation or recover from an error, you need to implement checkpoints and cancellation mechanisms, and to implement these mechanisms, you must save the state information somewhere before you can restore the object to their previous state. How do you implement this to keep state information in place? Use prototype mode? Because an object usually encapsulates some or all of its state information so that its state cannot be accessed by other objects, it is impossible to save its state outside the object. Since the prototype pattern always returns all the state information of the object, and the prototype pattern makes its state accessible to other objects, it violates the principle of encapsulation and may also compromise the reliability and scalability of the application.
Then take the above "Chinese paladin" for analysis, when we are playing Big boss before archiving, at this time need to match the game scene, task information, character information and so on state storage; When you win a big Boss, overwrite the previous archive, discard the previous archive, create a new archive, Save the current state information; If you lose, restore the archive, the previous archive information read out, restore to play Big Boss before the game scene, start playing Big boss again. This is the use of the memo mode.
A memo is an object that stores the internal state of another object in an instant, which is called a memo's original. When you need to set up a checkpoint for the original, the cancellation mechanism requests a memo from the original sender. The original sender initializes the memo with information describing the current state. Only the original can access the information to the memo, and the memo is "invisible" to the other objects.
UML Class Diagram
Memento: The memo stores the internal state of the original object. The original device determines which internal state of the memo stores the original, as needed, and prevents access to the memo for objects other than the original. The memo actually has two interfaces, and the manager sees only the narrow interface of the memo ———— it can only pass the memo to other objects. Instead, the primary can see a wide interface that allows it to access all the data it needs to return to its previous state. Ideally, only the source that generated the memo would be allowed to access the internal state of the memo;
Originator: The original device creates a memo that records its internal state at the moment; we use the memo to restore the internal state;
Caretaker: Be responsible for keeping the memo; However, the contents of the memo cannot be manipulated or checked.
The memo mode is coordinated in the following ways:
The manager requests a memo to the original, which is retained for a period of time, to be sent back to the original, and sometimes the manager does not return the memo to the original, because the original may not need to retreat to the previous state at all. The memo is passive, and only the original that creates the memo assigns and retrieves its state, as in the following sequence diagram:
Use occasion
Use Memo mode in the following situations:
1. You must save a part or a complete state of an object at a given moment so that it can revert to its previous state when needed;
2. If an interface is used to allow other objects to get these states directly, it exposes the implementation details of the object and destroys the encapsulation of the object.
Code implementation:
Copy Code code as follows:
#include <iostream>
using namespace Std;
struct state
{
wchar_t wcsstate[260];
};
Class Memento
{
Public
Memento (state *pstate): M_pstate (pstate) {}
State *getstate () {return m_pstate;}
Private
Friend class originator;
State *m_pstate;
};
Class originator
{
Public
Originator (): M_pstate (NULL) {}
~originator ()
{
Delete the storage of the state
if (m_pstate)
{
Delete m_pstate;
M_pstate = NULL;
}
}
void Setmemento (Memento *pmemento);
Memento *creatememento ();
void SetValue (wchar_t *value)
{
memset (wcsvalue, 0, sizeof (wchar_t));
wcscpy_s (Wcsvalue, the value);
}
void Printstate () {wcout<<wcsvalue<<endl;}
Private
State *m_pstate; To store the object "s state
wchar_t wcsvalue[260]; This is the object's real data
};
Memento *originator::creatememento ()
{
M_pstate = new State;
if (m_pstate = NULL)
{
return NULL;
}
Memento *pmemento = new Memento (m_pstate);
wcscpy_s (M_pstate->wcsstate, Wcsvalue); Backup the value
return pmemento;
}
void Originator::setmemento (Memento *pmemento)
{
M_pstate = Pmemento->getstate ();
Recovery the data
memset (wcsvalue, 0, sizeof (wchar_t));
wcscpy_s (Wcsvalue, m_pstate->wcsstate);
}
Manager the Memento
Class caretaker
{
Public
Memento *getmemento () {return m_pmemento;}
void Setmemnto (Memento *pmemento)
{
Free the previous Memento
if (M_pmemento)
{
Delete M_pmemento;
M_pmemento = NULL;
}
Set the new Memento
M_pmemento = Pmemento;
}
Private
Memento *m_pmemento;
};
int main ()
{
Originator *poriginator = new originator ();
Poriginator->setvalue (L "on");
Poriginator->printstate ();
Now I backup the state
Caretaker *pcaretaker = new Caretaker ();
Pcaretaker->setmemnto (Poriginator->creatememento ());
Set the new state
Poriginator->setvalue (L "off");
Poriginator->printstate ();
Recovery to the Old state
Poriginator->setmemento (Pcaretaker->getmemento ());
Poriginator->printstate ();
if (Pcaretaker)
{
Delete Pcaretaker;
}
if (poriginator)
{
Delete Poriginator;
}
return 0;
}
I then according to the above "paladin" to complete the memo mode, the code is as follows:
Copy Code code as follows:
#include <iostream>
using namespace Std;
Class Rolestatememento
{
Public
Rolestatememento (unsigned iblood, unsigned iattack, unsigned idefense): M_iblood (Iblood), M_iattack (iattack), m_ iDEFENSE (idefense) {}
Private
Friend class Gamerole;
Unsigned getbloodvalue () {return m_iblood;}
Unsigned getattackvalue () {return m_iattack;}
Unsigned getdefensevalue () {return m_idefense;}
unsigned m_iblood; Vitality
unsigned m_iattack; Attack
unsigned m_idefense; Defensive force
};
Class Gamerole
{
Public
Gamerole (): M_iblood (M), M_iattack (M), M_idefense (100) {}
Archive
Rolestatememento *savestate () {Return to New Rolestatememento (M_iblood, M_iattack, m_idefense);}
Restore Archive
void Recoverystate (Rolestatememento *prolestate)
{
M_iblood = Prolestate->getbloodvalue ();
M_iattack = Prolestate->getattackvalue ();
M_idefense = Prolestate->getdefensevalue ();
cout<< "Recovery ..." <<endl;
}
void Showstate ()
{
cout<< "Blood:" <<m_iBlood<<endl;
cout<< "Attack:" <<m_iAttack<<endl;
cout<< "Defense:" <<m_iDefense<<endl;
}
void Fight ()
{
M_iblood-= 100;
M_iattack-= 10;
M_idefense-= 20;
if (M_iblood = 0)
{
cout<< "Game over" <<endl;
}
}
Private
unsigned m_iblood; Vitality
unsigned m_iattack; Attack
unsigned m_idefense; Defensive force
};
Class Rolestatecaretaker
{
Public
void Setrolestatememento (Rolestatememento *prolestatememento) {m_prolestatememento = Prolestatememento;}
Rolestatememento *getrolestatememento () {return m_prolestatememento;}
Private
Rolestatememento *m_prolestatememento;
};
int main ()
{
Gamerole *plixy = new Gamerole (); To create the role of Li Xiaoyao
Plixy->showstate (); Show the initial state
Archive
Rolestatecaretaker *prolestatecaretaker = new Rolestatecaretaker ();
Prolestatecaretaker->setrolestatememento (Plixy->savestate ());
Start playing Big Boss
Plixy->fight ();
Plixy->showstate ();
Read the file, start anew
Plixy->recoverystate (Prolestatecaretaker->getrolestatememento ());
Plixy->showstate ();
return 0;
}
Summarize
Memo mode is also a lot of practical application, we are in the document editing, often use the undo operation. The key point in using C + + to implement Memo mode is that the originator class is a friend class of Memento, which makes it possible for the caretaker object of the management memo and other objects to read and set the memo, and only the originator class can read and set the memo. Because the memo is mainly used to backup the state of the object, implementation of the undo operation, if the object's state data is very large, in the preparation of the memory will be very resource, this is what we need to consider when the actual development. Combined with previous design patterns, when summing up command mode, when it comes to command mode to support the return of things, and this is dependent on the memo mode to achieve. Well, the memo pattern is summarized here. Hope to be useful to everyone.