This design pattern lets you save the state of an object without revealing the implementation.
There are mainly three participants in this design pattern
- Memento: stores the internal state of the Originator object. How much state of the Originator the memento will store completely depends upon the Originator
- Originator: It creates a memento containing a snapshot of its current internal state. It also uses the Memento to restore the Original state
Caretaker: It's responsible for the memento's safekeeping.
The memento design pattern helps to implement Undo facilities for any application. Think about a word processor app - at any point in time we can undo and get back the earlier state of the document - here lies the greatness of the memento design pattern.
The source code for the Memento Design Pattern is as follows:
class Originator:
"""
The Originator holds some state that may change over time. It also defines a
method for saving its state inside a memento and another method for
restoring the state from it.
"""
_state = ""
def set(self, state):
"""
Sets the state of the originator.
"""
print(f"Originator: Setting state to {state}")
self._state = state
def save_to_memento(self):
"""
Saves the current state inside a memento.
"""
return self.Memento(self._state)
def restore_from_memento(self, m):
"""
Restores the Originator's state from a memento object.
"""
self._state = m.get_saved_state()
print(f"Originator: State after restoring from Memento: {self._state}")
class Memento:
"""
The Memento stores the internal state of the Originator object. The
memento may expose the state to the world, but it should be done in a
way that prevents the originator from being tampered with.
"""
def __init__(self, state):
self._state = state
def get_saved_state(self):
"""
Returns the saved state.
"""
return self._state
class Caretaker:
"""
The Caretaker doesn't depend on the Concrete Memento class. Therefore, it
doesn't have access to the originator's state, stored inside the memento. It
works with all mementos via the base Memento interface.
"""
def __init__(self, originator):
self.originator = originator
self.saved_states = []
def save_state(self):
"""
Saves the current state of the originator.
"""
print("Caretaker: Saving Originator's state...")
self.saved_states.append(self.originator.save_to_memento())
def undo(self):
"""
Restores the last saved state.
"""
if not self.saved_states:
print("Caretaker: No saved states to restore.")
return
print("Caretaker: Restoring state...")
self.originator.restore_from_memento(self.saved_states.pop())
if __name__ == '__main__':
originator = Originator()
caretaker = Caretaker(originator)
originator.set("State1")
caretaker.save_state()
originator.set("State2")
caretaker.save_state()
originator.set("State3")
caretaker.save_state()
originator.set("State4")
caretaker.save_state()
print("\nClient: Now, let's rollback!\n")
caretaker.undo()
print("\nClient: Once more!\n")
caretaker.undo()
print("\nClient: One last time, to show it handles an empty stack!\n")
caretaker.undo()
caretaker.undo()
If we run the above lines of code, the output will be:
Originator: Setting state to State1
Originator: Setting state to State2
Originator: Setting state to State3
Originator: Setting state to State4
Client: Now, let's rollback!
Originator: State after restoring from Memento: State4
Client: Once more!
Originator: State after restoring from Memento: State3
Top comments (0)