备忘录模式(Memento)
是行为模式之一。
概念:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
从命名基本上可以了解到这个模式的作用,我们都知道无论是以前的手机还是现在的手机,都会有备忘录这个功能,备忘录的作用是什么呢?
防止人脑记不住的时候,记录到备忘录里面,可以随时拿出来提醒自己,就像是日志文件一样。
概念:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
从命名基本上可以了解到这个模式的作用,我们都知道无论是以前的手机还是现在的手机,都会有备忘录这个功能,备忘录的作用是什么呢?
防止人脑记不住的时候,记录到备忘录里面,可以随时拿出来提醒自己,就像是日志文件一样。
例如:作为开发人员,一定会用到的一个组合键Ctrl + Z就是这个原理。
如下代码模拟水桶抽水多次回退效果。
<?php header("Content-Type:text/html;charset=utf-8"); //-------------------------备忘录模式------------------------ require_once "Memento.php"; echo "<pre>"; $water = new Bucket(); // 实例化水桶类 $water->Initialize(); // 初始化赋值 $water->ShowWaterLevel(); // 显示水位 $SL = new SaveWater(); // 实例储水类 echo "----------------------第一次抽水----------------------<br/>"; $water->DrawOff(); // 抽水 $waterlevel = $water->SaveWaterLevel(); // 保存水位返回水位值 $SL->SaveArrayWater($waterlevel); // 存到备忘录 $water->ShowWaterLevel(); // 展示水位 echo "-----------------------回退一次----------------------<br/>"; $water->RecoveryWaterLevel($SL->memento);// 回退水位 $water->ShowWaterLevel(); // 展示水位 echo "----------------------第二次抽水----------------------<br/>"; $water->DrawOff(); // 抽水 $waterlevel = $water->SaveWaterLevel(); // 保存水位返回水位值 $SL->SaveArrayWater($waterlevel); // 存到备忘录 $water->ShowWaterLevel(); // 展示水位 echo "----------------------第三次抽水----------------------<br/>"; $water->DrawOff(); // 抽水 $waterlevel = $water->SaveWaterLevel(); // 保存水位返回水位值 $SL->SaveArrayWater($waterlevel); // 存到备忘录 $water->ShowWaterLevel(); // 展示水位 echo "-----------------------回退一次----------------------<br/>"; $water->RecoveryWaterLevel($SL->memento);// 回退水位 $water->ShowWaterLevel(); // 展示水位 echo "----------------------第四次抽水----------------------<br/>"; $water->DrawOff(); // 抽水 $waterlevel = $water->SaveWaterLevel(); // 保存水位返回水位值 $SL->SaveArrayWater($waterlevel); // 存到备忘录 $water->ShowWaterLevel(); // 展示水位 echo "----------------------第五次抽水----------------------<br/>"; $water->DrawOff(); // 抽水 $waterlevel = $water->SaveWaterLevel(); // 保存水位返回水位值 $SL->SaveArrayWater($waterlevel); // 存到备忘录 $water->ShowWaterLevel(); // 展示水位
<?php // Bucket 水桶类 Class Bucket { /** * 水位值 * @var int */ public $waterLevel; /** * 备忘录对象 * @var object */ public $Memento; /** * 初始化水位值 * @access public */ public function Initialize() { $this->waterLevel = 100; } /** * 保存水位函数 * @access public */ public function SaveWaterLevel() { // 查看保存备忘录对象是否存在 if($this->Memento) { // 调用保存备忘录函数 $levelwater = $this->Memento->SaveMemento($this->waterLevel); }else{ $this->Memento = new SaveWaterMemento(); $levelwater = $this->Memento->SaveMemento($this->waterLevel); } return $levelwater; } /** * 回退函数 * @access public * @param array $_Memento 参数名 */ public function RecoveryWaterLevel($_Memento) { if(count($_Memento) == 1) { $this->Initialize(); } else{ $this->waterLevel = $_Memento[count($_Memento)-2]; } } /** * 显示水位函数 * @access public */ public function ShowWaterLevel() { echo "水位刻度为:{$this->waterLevel}L<br/>"; } /** * 抽水函数 * @access public */ public function DrawOff() { $this->waterLevel -= 20; if($this->waterLevel < 0) { echo "水已经放光了!---"; die; } } } // 保存水位备忘录类 Class SaveWaterMemento { /** * 水位池 * @var array */ public $waterLevel = array(); /** * 水位池游标 * @var int */ private $i = 0; /** * 回退函数 * @access public * @param int $_Memento 水位值 */ function SaveMemento($_WL) { $this->waterLevel[$this->i] = $_WL; $this->i++; return $this->waterLevel[$this->i-1]; } } // 保存水位类 Class SaveWater { /** * 水位池 * @var array */ public $memento = array(); /** * 水位池游标 * @var int */ private $i = 0; /** * 保存水位 * @access public * @param int $waterlevel 水位值 */ public function SaveArrayWater($waterlevel) { $this->memento[$this->i] = $waterlevel; $this->i++; } }
输出结果:
水位刻度为:100L ----------------------第一次抽水---------------------- 水位刻度为:80L -----------------------回退一次---------------------- 水位刻度为:100L ----------------------第二次抽水---------------------- 水位刻度为:80L ----------------------第三次抽水---------------------- 水位刻度为:60L -----------------------回退一次---------------------- 水位刻度为:80L ----------------------第四次抽水---------------------- 水位刻度为:60L ----------------------第五次抽水---------------------- 水位刻度为:40L