備忘錄模式(Memento Pattern)
定義
在不違背封裝原則的前提下,捕獲一個物件的內部狀態,並在該物件之外儲存這個狀態,以便之後恢復物件為先前的狀態。
設計的原則和思想
- 解耦的是物件狀態的歷史記錄和恢復。
- 不變部分是恢復,變化部分是物件狀態。
- 核心思想是物件的備份與恢復。
一句話概括設計模式
把物件歷史的狀態儲存起來,需要的時候可以恢復。
結構中包含的角色
- Originator(原發器)管理備忘錄。
- Memento(備忘錄) 儲存內部狀態。
- Caretaker(負責人) 儲存備忘錄。
最小可表達程式碼
class Originator
{
private $state;
public function createMemento()
{
return new Memento($this);
}
public function restoreMemento(Memento $m)
{
$this->state = $m->getState();
}
public function setState(String $state)
{
$this->state = $state;
}
public function getState()
{
return $this->state;
}
}
class Memento
{
private $state;
public function __construct(Originator $o)
{
$this->state = $o->getState();
}
public function getState()
{
return $this->state;
}
}
class Caretaker
{
private $memento;
public function getMemento()
{
return $this->memento;
}
public function setMemento(Memento $memento)
{
$this->memento = $memento;
}
}
$originator = new Originator();
$originator->setState("遊戲存檔10%");
$careTaker = new CareTaker();
$careTaker->setMemento($originator->createMemento());
$originator->setState("遊戲存檔30%");
$originator->setState("遊戲存檔50%");
$originator->restoreMemento($careTaker->getMemento());
var_dump($originator->getState());
優點
- 在不破壞物件封裝的情況下建立物件狀態快照。
- 可以方便地回到某個狀態。
缺點
- 每一次儲存物件狀態都會消耗一定的記憶體,隨著狀態增多,消耗的記憶體也會逐漸增多。
- 對於大物件的備份來說,備份和恢復的耗時會比較長。
何時使用
- 需要儲存/恢復資料的場景
實際應用場景
- 打遊戲時的存檔。
- Windows裡的ctrl + z。
- 瀏覽器中的後退。
- 資料庫的事務管理。
- 編輯器撤銷與重做。
- 虛擬機器生成快照與恢復。
- Git版本管理。
本作品採用《CC 協議》,轉載必須註明作者和本文連結