Memento Page 283 Jason Penny Memento n n
- Slides: 12
Memento Page 283 Jason Penny
Memento n n Behavioral Pattern Intent: n n Without violating encapsulation, capture and externalize an object’s internal state so that the object can be restored to this state later Sometimes its necessary to record the internal state of an object n n When implementing checkpoints When implementing undo mechanisms for both backing out of tentative operations and for recovering from errors
Problem: n We don’t want objects to expose their details to provide save and restore functionality, this would violate encapsulation n A memento is a copy of the minimal information required to rebuild the object’s state, so large objects can be rebuilt using smaller mementos
Memento Class Diagram Caretaker Originator Memento create. Memento() set. Memento() get. State() state return new Memento(state) state = memento->get. State()
Memento Interaction Diagram a. Caretaker an. Originator create. Memento() new Memento set. State() set. Memento(a. Memento) get. State() a. Memento
Supporting Undo n n Sometimes reversing the actions on an object does not return the object to its previous state Consider a connected line class that insures that a line always connects the two rectangles it is associated with
Reversing the Operations n n In this case, reversing the operation produces a different result than we started with Using a memento to save and restore the state solves this problem
Implementation class State; class Originator { public: Memento* Create. Memento(); void Set. Memento( const Memento* ); //. . . private: State* _state; // internal data structures //. . . }; class Memento { public: // narrow public interface virtual ~Memento(); private: // private members accessible // only to Originator friend class Originator; Memento(); void Set. State( State* ); State* Get. State(); //. . . private: State* _state; //. . . };
Summary: Consequences Preserving encapsulation boundaries n It simplifies Originator n Using mementos might be expensive n Defining narrow and wide interfaces n Hidden costs in caring for mementos n
Sample Code class Graphic; // base class for graphical objects in the graphical editor class Move. Command { public: Move. Command( Graphic* target, const Point& delta ); void Execute(); void Unexecute(); private: Constraint. Solver. Memento* _state; Point _delta; Graphic* target; }
Sample Code Continued class Constraint. Solver { public: static Constraint. Solver* Instance(); void Solve(); void Add. Constraint( Graphic* start. Connection, Graphic* end. Connection ); void Remove. Connection( Graphic* start. Connection, Graphic* end. Connection ); Constraint. Solver. Memento* Create. Memento(); void Set. Memento( Constaint. Solver. Memento* ); private: // nontrivial state and operations for enforcing // connectivity semantics };
void Move. Command: : Execute() { Constraint. Solver* solver = Constraint. Solver: : Instance(); _state = solver->Create. Memento(); // create a Memento _target->Move( _delta ); solver->Solve(); } void Move. Command: : Unexecute() { Constraint. Solver* solver = Constraint. Solver: : Instance(); _target->Move( -_delta ); solver->Set. Memento( _state ); // restore solver state solver->Solve(); }