简介

容许在不裸露对象实现细节的状况下保留和复原对象之前的状态,该状态保留在对象之外,这样就能够不毁坏原有对象的封装性了。

角色

  • Originator 原发器

    即须要被保留状态的类

  • 形象 Memento 备忘录类

    定义备忘录根本接口

    能够看做成是快照 Snapshot

  • 具体 Memento 备忘录类

    实现接口

  • Caretaker 负责人

    即连贯Originator和Memento的类,保护一个Memento队列,通过操作队列实现undo redo的操作

类图

图中,ConcreteOriginator通过save办法,生成一个Memento,Caretaker 的history属性保留这些Memento,实现undo操作。

代码

class Originator{    private $state;    public function __construct(string $state)    {        $this->state = $state;        echo "Originator: My initial state is: {$this->state}\n";    }    public function doSomething(): void    {        echo "Originator: I'm doing something important.\n";        $this->state = $this->generateRandomString(30);        echo "Originator: and my state has changed to: {$this->state}\n";    }    private function generateRandomString(int $length = 10): string    {        return substr(            str_shuffle(                str_repeat(                    $x = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',                    ceil($length / strlen($x))                )            ),            1,            $length        );    }    public function save(): Memento    {        return new ConcreteMemento($this->state);    }    public function restore(Memento $memento): void    {        $this->state = $memento->getState();        echo "Originator: My state has changed to: {$this->state}\n";    }}interface Memento{    public function getName(): string;    public function getDate(): string;}class ConcreteMemento implements Memento{    private $state;    private $date;    public function __construct(string $state)    {        $this->state = $state;        $this->date = date('Y-m-d H:i:s');    }    public function getState(): string    {        return $this->state;    }    public function getName(): string    {        return $this->date . " / (" . substr($this->state, 0, 9) . "...)";    }    public function getDate(): string    {        return $this->date;    }}class Caretaker{    private $mementos = [];    private $originator;    public function __construct(Originator $originator)    {        $this->originator = $originator;    }    public function backup(): void    {        echo "\nCaretaker: Saving Originator's state...\n";        $this->mementos[] = $this->originator->save();    }    public function undo(): void    {        if (!count($this->mementos)) {            return;        }        $memento = array_pop($this->mementos);        echo "Caretaker: Restoring state to: " . $memento->getName() . "\n";        try {            $this->originator->restore($memento);        } catch (\Exception $e) {            $this->undo();        }    }    public function showHistory(): void    {        echo "Caretaker: Here's the list of mementos:\n";        foreach ($this->mementos as $memento) {            echo $memento->getName() . "\n";        }    }}$originator = new Originator("Super-duper-super-puper-super.");$caretaker = new Caretaker($originator);$caretaker->backup();$originator->doSomething();$caretaker->backup();$originator->doSomething();$caretaker->backup();$originator->doSomething();echo "\n";$caretaker->showHistory();echo "\nClient: Now, let's rollback!\n\n";$caretaker->undo();echo "\nClient: Once more!\n\n";$caretaker->undo();

output:

Originator: My initial state is: Super-duper-super-puper-super.Caretaker: Saving Originator's state...Originator: I'm doing something important.Originator: and my state has changed to: uDdcJyRkbMEFqaKnpHiYQtrzWjXPVICaretaker: Saving Originator's state...Originator: I'm doing something important.Originator: and my state has changed to: YrymDJvtFqlwGpMuCNXadsQonIVPzRCaretaker: Saving Originator's state...Originator: I'm doing something important.Originator: and my state has changed to: pOuLBUelsmFRkKrbhAGfqzTtQXjnNHCaretaker: Here's the list of mementos:2023-06-28 01:51:01 / (Super-dup...)2023-06-28 01:51:01 / (uDdcJyRkb...)2023-06-28 01:51:01 / (YrymDJvtF...)Client: Now, let's rollback!Caretaker: Restoring state to: 2023-06-28 01:51:01 / (YrymDJvtF...)Originator: My state has changed to: YrymDJvtFqlwGpMuCNXadsQonIVPzRClient: Once more!Caretaker: Restoring state to: 2023-06-28 01:51:01 / (uDdcJyRkb...)Originator: My state has changed to: uDdcJyRkbMEFqaKnpHiYQtrzWjXPVI

本文由mdnice多平台公布