mirror of
https://github.com/rjNemo/design-patterns
synced 2026-06-06 02:26:40 +00:00
add code example
This commit is contained in:
parent
4e47e54507
commit
90149cb7be
5 changed files with 151 additions and 0 deletions
34
behavioral/memento/caretaker.py
Normal file
34
behavioral/memento/caretaker.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
from behavioral.memento.originator import Originator
|
||||
|
||||
|
||||
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: Originator) -> None:
|
||||
self._memento = []
|
||||
self._originator = originator
|
||||
|
||||
def backup(self) -> None:
|
||||
print("\nCaretaker: Saving Originator's state...")
|
||||
self._memento.append(self._originator.save())
|
||||
|
||||
def undo(self) -> None:
|
||||
if not self._memento:
|
||||
return
|
||||
|
||||
memento = self._memento.pop()
|
||||
print(f"Caretaker: Restoring state to: {memento.get_name()}")
|
||||
|
||||
try:
|
||||
self._originator.restore(memento)
|
||||
except Exception:
|
||||
self.undo()
|
||||
|
||||
def show_history(self) -> None:
|
||||
print("Caretaker: Here's the list of mementos:")
|
||||
for memento in self._memento:
|
||||
print(memento.get_name())
|
||||
25
behavioral/memento/concrete_memento.py
Normal file
25
behavioral/memento/concrete_memento.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
from datetime import datetime
|
||||
|
||||
from behavioral.memento.memento import Memento
|
||||
|
||||
|
||||
class ConcreteMemento(Memento):
|
||||
|
||||
def __init__(self, state: str) -> None:
|
||||
self._state = state
|
||||
self._date = str(datetime.now())[:19]
|
||||
|
||||
def get_state(self) -> str:
|
||||
"""
|
||||
The Originator uses this method when restoring its state.
|
||||
"""
|
||||
return self._state
|
||||
|
||||
def get_name(self) -> str:
|
||||
"""
|
||||
The rest of the methods are used by the Caretaker to display metadata.
|
||||
"""
|
||||
return f"{self._date} / ({self._state[0:9]}...)"
|
||||
|
||||
def get_date(self) -> str:
|
||||
return self._date
|
||||
20
behavioral/memento/main.py
Normal file
20
behavioral/memento/main.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
from behavioral.memento.caretaker import Caretaker
|
||||
from behavioral.memento.originator import Originator
|
||||
|
||||
originator = Originator("Super-duper-super-puper-super.")
|
||||
caretaker = Caretaker(originator)
|
||||
|
||||
caretaker.backup()
|
||||
originator.do_something()
|
||||
|
||||
caretaker.backup()
|
||||
originator.do_something()
|
||||
|
||||
print()
|
||||
caretaker.show_history()
|
||||
|
||||
print("\nClient: Now, let's rollback!\n")
|
||||
caretaker.undo()
|
||||
|
||||
print("\nClient: Once more!\n")
|
||||
caretaker.undo()
|
||||
21
behavioral/memento/memento.py
Normal file
21
behavioral/memento/memento.py
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class Memento(ABC):
|
||||
"""
|
||||
The Memento interface provides a way to retrieve the memento's metadata,
|
||||
such as creation date or name. However, it doesn't expose the Originator's
|
||||
state.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def get_state(self) -> str:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_name(self) -> str:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_date(self) -> str:
|
||||
pass
|
||||
51
behavioral/memento/originator.py
Normal file
51
behavioral/memento/originator.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
from random import sample
|
||||
from string import ascii_letters
|
||||
|
||||
from behavioral.memento.concrete_memento import ConcreteMemento
|
||||
from behavioral.memento.memento import Memento
|
||||
|
||||
|
||||
class Originator:
|
||||
"""
|
||||
The Originator holds some important state that may change over time. It also
|
||||
defines a method for saving the state inside a memento and another method
|
||||
for restoring the state from it.
|
||||
"""
|
||||
|
||||
"""
|
||||
For the sake of simplicity, the originator's state is stored inside a single
|
||||
variable.
|
||||
"""
|
||||
_state = None
|
||||
|
||||
def __init__(self, state: str) -> None:
|
||||
self._state = state
|
||||
print(f"Originator: My initial state is: {self._state}")
|
||||
|
||||
def do_something(self) -> None:
|
||||
"""
|
||||
The Originator's business logic may affect its internal state.
|
||||
Therefore, the client should backup the state before launching methods
|
||||
of the business logic via the save() method.
|
||||
"""
|
||||
print("Originator: I'm doing something important.")
|
||||
self._state = self._generate_random_string(30)
|
||||
print(f"Originator: and my state has changed to: {self._state}")
|
||||
|
||||
def _generate_random_string(self, length: int) -> str:
|
||||
return "".join(sample(ascii_letters, length))
|
||||
|
||||
def save(self) -> Memento:
|
||||
"""
|
||||
Saves the current state inside a memento.
|
||||
"""
|
||||
return ConcreteMemento(self._state)
|
||||
|
||||
def restore(self, memento: Memento) -> None:
|
||||
"""
|
||||
Restores the Originator's state from a memento object.
|
||||
"""
|
||||
|
||||
self._state = memento.get_state()
|
||||
|
||||
print(f"Originator: My state has changed to: {self._state}")
|
||||
Loading…
Reference in a new issue