写点什么

行为型设计模式 - 备忘录 Memento

作者:菜皮日记
  • 2023-09-08
    北京
  • 本文字数:2688 字

    阅读完需:约 9 分钟

简介

允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态,该状态保存在对象之外,这样就可以不破坏原有对象的封装性了。

角色

  • 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: uDdcJyRkbMEFqaKnpHiYQtrzWjXPVI
Caretaker: Saving Originator's state...Originator: I'm doing something important.Originator: and my state has changed to: YrymDJvtFqlwGpMuCNXadsQonIVPzR
Caretaker: Saving Originator's state...Originator: I'm doing something important.Originator: and my state has changed to: pOuLBUelsmFRkKrbhAGfqzTtQXjnNH
Caretaker: 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: YrymDJvtFqlwGpMuCNXadsQonIVPzR
Client: Once more!
Caretaker: Restoring state to: 2023-06-28 01:51:01 / (uDdcJyRkb...)Originator: My state has changed to: uDdcJyRkbMEFqaKnpHiYQtrzWjXPVI
复制代码


用户头像

菜皮日记

关注

全干程序员 2018-08-08 加入

还未添加个人简介

评论

发布
暂无评论
行为型设计模式-备忘录 Memento_设计模式_菜皮日记_InfoQ写作社区