github地址:https://github.com/ZQCard/design_pattern
/** * 备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象. * 所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。 * 很多时候我们总是需要记录一个对象的内部状态,这样做的目的就是为了允许用户取消不确定或者错误的操作,能够恢复到他原先的状态,使得他有"后悔药"可吃。 * 优点: * 1、给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。 * 2、实现了信息的封装,使得用户不需要关心状态的保存细节。 * 缺点:消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。 * 使用场景: * 1、需要保存/恢复数据的相关状态场景。 * 2、提供一个可回滚的操作。 * 注意事项: * 1、为了符合迪米特原则,还要增加一个管理备忘录的类。 * 2、为了节约内存,可使用原型模式+备忘录模式。 */
备忘录模式使用三个类 Memento、Originator 和 CareTaker。Memento 包含了要被恢复的对象的状态。Originator 创建并在 Memento 对象中存储状态。Caretaker 对象负责从 Memento 中恢复对象的状态。
(1)Memento.class.php (备忘录类)
<?php namespace Memento; class Memento { private $state; public function __construct($state) { $this->state = $state; } public function getState() { return $this->state; } }
(2) Originator.class.php(要保存的对象类)
<?php namespace Memento; class Originator { private $state; public function setState($state) { $this->state = $state; } public function getState() { return $this->state; } public function saveStateToMemento() { return new Memento($this->state); } public function getStateFromMemento(Memento $memento) { $this->state = $memento->getState(); } }
(3)CareTaker.class.php (备忘录提取类)
<?php namespace Memento; class CareTalker { private $memento = []; public function add(Memento $memento) { $this->memento[] = $memento; } public function get($index) { return $this->memento[$index]; } }
(4)memento.php(客户端类)
<?php spl_autoload_register(function ($className){ $className = str_replace('\','/',$className); include $className.".class.php"; }); use MementoOriginator; use MementoCareTalker; $originator = new Originator(); $careTaker = new CareTalker(); $originator->setState("STATE #1"); $careTaker->add($originator->saveStateToMemento()); $originator->setState("STATE #2"); $careTaker->add($originator->saveStateToMemento()); $originator->setState("STATE #3"); $careTaker->add($originator->saveStateToMemento()); echo "Current State: " . $originator->getState(); echo '<br/>'; echo "First State: " . $careTaker->get(0)->getState(); echo '<br/>'; echo "Second State: " . $careTaker->get(1)->getState();