備忘錄模式又叫做快照模式或Token模式,在不破壞封閉的前提下,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài)。這樣以后就可將該對象恢復(fù)到原先保存的狀態(tài)。
UML類圖:

角色:
1.發(fā)起人(GameRole):負(fù)責(zé)創(chuàng)建一個備忘錄,用以記錄當(dāng)前時刻自身的內(nèi)部狀態(tài),并可使用備忘錄恢復(fù)內(nèi)部狀態(tài)。發(fā)起人可以根據(jù)需要決定備忘錄存儲自己的哪些內(nèi)部狀態(tài)。
2.備忘錄(RoleStateSaveBox):負(fù)責(zé)存儲發(fā)起人對象的內(nèi)部狀態(tài),并可以防止發(fā)起人以外的其他對象訪問備忘錄。備忘錄有兩個接口:管理者只能看到備忘錄的窄接口,他只能將備忘錄傳遞給其他對象。發(fā)起人卻可看到備忘錄的寬接口,允許它訪問返回到先前狀態(tài)所需要的所有數(shù)據(jù)。
3.管理者(GameRoleStateManager):負(fù)責(zé)存取備忘錄,不能對的內(nèi)容進(jìn)行訪問或者操作。
核心代碼:
<?php
/**
* Created by PhpStorm.
* User: Jang
* Date: 2015/6/10
* Time: 9:49
*/
//游戲角色
class GameRole
{
#region 游戲角色狀態(tài)屬性(生命力、攻擊力、防御力)
public $liveLevel;
public $attackLevel;
public $defenseLevel;
#endregion
//保存狀態(tài)
public function SaveState()
{
return (new RoleStateMemento($this->liveLevel,$this->attackLevel,$this->defenseLevel));
}
//恢復(fù)狀態(tài)
public function RecoveryState(RoleStateMemento $_memento)
{
$this->liveLevel = $_memento->liveLevel;
$this->attackLevel = $_memento->attackLevel;
$this->defenseLevel = $_memento->defenseLevel;
}
//------------其他屬性及操作--------------
//獲得初始狀態(tài)
public function GetInitState()
{
$this->defenseLevel = 100;
$this->attackLevel = 100;
$this->liveLevel = 100;
}
//狀態(tài)顯示
public function StateDisplay()
{
echo "角色狀態(tài):<br/>";
echo "生命力:{$this->liveLevel}<br/>";
echo "攻擊力:{$this->attackLevel}<br/>";
echo "防御力:{$this->defenseLevel}<br/>";
}
//被攻擊
public function BeenAttack()
{
$this->liveLevel -= 9.5;
if($this->liveLevel<=0)
{
$this->liveLevel = 0;
echo "呃,該角色陣亡了!<br/>";
echo "Game Over!<br/>";
return;
}
$this->attackLevel -= 1.1;
if($this->attackLevel<=0)
{
$this->attackLevel = 0;
}
$this->defenseLevel -= 0.5;
if($this->defenseLevel<=0)
{
$this->defenseLevel = 0;
}
}
}
//角色狀態(tài)存儲箱類
class RoleStateMemento
{
public $liveLevel;
public $attackLevel;
public $defenseLevel;
public function RoleStateMemento($_ll,$_al,$_dl)
{
$this->liveLevel=$_ll;
$this->attackLevel=$_al;
$this->defenseLevel=$_dl;
}
}
//游戲角色狀態(tài)管理者類
class RoleStateManager
{
public $memento;
}
測試代碼:
<?php
/**
* Created by PhpStorm.
* User: Jang
* Date: 2015/6/10
* Time: 10:02
*/
header("Content-Type:text/html;charset=utf-8");
//-------------------------備忘錄模式------------------------
require_once "./Memento/Memento.php";
//開戰(zhàn)前
$ufo = new GameRole();
$ufo->GetInitState();
echo "<span style='color:#ff0000'>----------------開戰(zhàn)前-----------------</span><br/>";
$ufo->StateDisplay();
//保存進(jìn)度
$roleMan = new RoleStateManager();
$roleMan->memento = $ufo->SaveState();
echo "<span style='color:#ff0000'>----------------戰(zhàn)斗中-----------------</span><br/>";
$num=1;
//大戰(zhàn)Boss5個回合
for ($i = 0; $i <13;$i++ )
{
echo "-------------第{$num}回合-------------<br/>";
$ufo->BeenAttack();
$ufo->StateDisplay();
$num++;
//角色陣亡
if($ufo->liveLevel<=0)
{
break;
}
}
echo "<span style='color:#ff0000'>----------------恢復(fù)狀態(tài)-----------------</span><br/>";
//恢復(fù)之前狀態(tài)
$ufo->RecoveryState($roleMan->memento);
$ufo->StateDisplay();
優(yōu)點:
1、有時一些發(fā)起人對象的內(nèi)部信息必須保存在發(fā)起人對象以外的地方,但是必須要由發(fā)起人對象自己讀取,這時,使用備忘錄模式可以把復(fù)雜的發(fā)起人內(nèi)部信息對其他的對象屏蔽起來,從而可以恰當(dāng)?shù)乇3址庋b的邊界。
2、本模式簡化了發(fā)起人類。發(fā)起人不再需要管理和保存其內(nèi)部狀態(tài)的一個個版本,客戶端可以自行管理他們所需要的這些狀態(tài)的版本。
缺點:
1、如果發(fā)起人角色的狀態(tài)需要完整地存儲到備忘錄對象中,那么在資源消耗上面?zhèn)渫泴ο髸馨嘿F。
2、當(dāng)負(fù)責(zé)人角色將一個備忘錄存儲起來的時候,負(fù)責(zé)人可能并不知道這個狀態(tài)會占用多大的存儲空間,從而無法提醒用戶一個操作是否很昂貴。
參考:《大話設(shè)計模式》,作者程杰
https://blog.csdn.net/jhq0113/article/details/46438735