130 likes | 260 Views
Memento. Page 283 Jason Penny. Memento. Behavioral Pattern Intent: 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
E N D
Memento Page 283 Jason Penny
Memento • Behavioral Pattern • Intent: • 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 • When implementing checkpoints • When implementing undo mechanisms for both backing out of tentative operations and for recovering from errors
Problem: • We don’t want objects to expose their details to provide save and restore functionality, this would violate encapsulation • 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 Originator getState()setState() state createMemento()setMemento() state return new Memento(state) Memento Class Diagram Caretaker state = memento->getState()
Memento Interaction Diagram aCaretaker anOriginator aMemento createMemento() new Memento setState() setMemento(aMemento) getState()
Supporting Undo • 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 • 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 Memento { public: // narrow public interface virtual ~Memento(); private: // private members accessible // only to Originator friend class Originator; Memento(); void SetState( State* ); State* GetState(); // ... private: State* _state; // ... }; class State; class Originator { public: Memento* CreateMemento(); void SetMemento( const Memento* ); // ... private: State* _state; // internal data structures // ... };
Summary: Consequences Preserving encapsulation boundaries It simplifies Originator Using mementos might be expensive Defining narrow and wide interfaces Hidden costs in caring for mementos
Sample Code class Graphic; // base class for graphical objects in the graphical editor class MoveCommand { public: MoveCommand( Graphic* target, const Point& delta ); void Execute(); void Unexecute(); private: ConstraintSolverMemento* _state; Point _delta; Graphic* target; }
Sample Code Continued class ConstraintSolver { public: static ConstraintSolver* Instance(); void Solve(); void AddConstraint( Graphic* startConnection, Graphic* endConnection ); void RemoveConnection( Graphic* startConnection, Graphic* endConnection ); ConstraintSolverMemento* CreateMemento(); void SetMemento( ConstaintSolverMemento* ); private: // nontrivial state and operations for enforcing // connectivity semantics };
void MoveCommand::Execute() { ConstraintSolver* solver = ConstraintSolver::Instance(); _state = solver->CreateMemento(); // create a Memento _target->Move( _delta ); solver->Solve(); } void MoveCommand::Unexecute() { ConstraintSolver* solver = ConstraintSolver::Instance(); _target->Move( -_delta ); solver->SetMemento( _state ); // restore solver state solver->Solve(); }