备忘录模式又叫做快照模式或Token模式,在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
UML类图:
图片.png
角色:
1.发起人(GameRole):负责创建一个备忘录,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。发起人可以根据需要决定备忘录存储自己的哪些内部状态。
2.备忘录(RoleStateSaveBox):负责存储发起人对象的内部状态,并可以防止发起人以外的其他对象访问备忘录。备忘录有两个接口:管理者只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。发起人却可看到备忘录的宽接口,允许它访问返回到先前状态所需要的所有数据。
3.管理者(GameRoleStateManager):负责存取备忘录,不能对的内容进行访问或者操作。
核心代码:
/**
* Created by PhpStorm.
* User: Jang
* Date: 2015/6/10
* Time: 9:49
*/
//游戏角色
class GameRole
{
#region 游戏角色状态属性(生命力、攻击力、防御力)
public $liveLevel;
public $attackLevel;
public $defenseLevel;
#endregion
//保存状态
public function SaveState()
{
return (new RoleStateMemento($this->liveLevel,$this->attackLevel,$this->defenseLevel));
}
//恢复状态
public function RecoveryState(RoleStateMemento $_memento)
{
$this->liveLevel = $_memento->liveLevel;
$this->attackLevel = $_memento->attackLevel;
$this->defenseLevel = $_memento->defenseLevel;
}
//------------其他属性及操作--------------
//获得初始状态
public function GetInitState()
{
$this->defenseLevel = 100;
$this->attackLevel = 100;
$this->liveLevel = 100;
}
//状态显示
public function StateDisplay()
{
echo "角色状态:
";
echo "生命力:{$this->liveLevel}
";
echo "攻击力:{$this->attackLevel}
";
echo "防御力:{$this->defenseLevel}
";
}
//被攻击
public function BeenAttack()
{
$this->liveLevel -= 9.5;
if($this->liveLevel<=0)
{
$this->liveLevel = 0;
echo "呃,该角色阵亡了!
";
echo "Game Over!
";
return;
}
$this->attackLevel -= 1.1;
if($this->attackLevel<=0)
{
$this->attackLevel = 0;
}
$this->defenseLevel -= 0.5;
if($this->defenseLevel<=0)
{
$this->defenseLevel = 0;
}
}
}
//角色状态存储箱类
class RoleStateMemento
{
public $liveLevel;
public $attackLevel;
public $defenseLevel;
public function RoleStateMemento($_ll,$_al,$_dl)
{
$this->liveLevel=$_ll;
$this->attackLevel=$_al;
$this->defenseLevel=$_dl;
}
}
//游戏角色状态管理者类
class RoleStateManager
{
public $memento;
}
测试代码:
/**
* 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";
//开战前
$ufo = new GameRole();
$ufo->GetInitState();
echo "----------------开战前-----------------
";
$ufo->StateDisplay();
//保存进度
$roleMan = new RoleStateManager();
$roleMan->memento = $ufo->SaveState();
echo "----------------战斗中-----------------
";
$num=1;
//大战Boss5个回合
for ($i = 0; $i <13;$i++ )
{
echo "-------------第{$num}回合-------------
";
$ufo->BeenAttack();
$ufo->StateDisplay();
$num++;
//角色阵亡
if($ufo->liveLevel<=0)
{
break;
}
}
echo "----------------恢复状态-----------------
";
//恢复之前状态
$ufo->RecoveryState($roleMan->memento);
$ufo->StateDisplay();
优点:
1、有时一些发起人对象的内部信息必须保存在发起人对象以外的地方,但是必须要由发起人对象自己读取,这时,使用备忘录模式可以把复杂的发起人内部信息对其他的对象屏蔽起来,从而可以恰当地保持封装的边界。
2、本模式简化了发起人类。发起人不再需要管理和保存其内部状态的一个个版本,客户端可以自行管理他们所需要的这些状态的版本。
缺点:
1、如果发起人角色的状态需要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象会很昂贵。
2、当负责人角色将一个备忘录存储起来的时候,负责人可能并不知道这个状态会占用多大的存储空间,从而无法提醒用户一个操作是否很昂贵。