極簡設計模式-備忘錄模式

long2ge發表於2021-12-10

備忘錄模式(Memento Pattern)

定義

在不違背封裝原則的前提下,捕獲一個物件的內部狀態,並在該物件之外儲存這個狀態,以便之後恢復物件為先前的狀態。

設計的原則和思想

  1. 解耦的是物件狀態的歷史記錄和恢復。
  2. 不變部分是恢復,變化部分是物件狀態。
  3. 核心思想是物件的備份與恢復。

一句話概括設計模式

把物件歷史的狀態儲存起來,需要的時候可以恢復。

結構中包含的角色

  1. Originator(原發器)管理備忘錄。
  2. Memento(備忘錄) 儲存內部狀態。
  3. 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()); // 突然想回到10%的時候
var_dump($originator->getState()); // 列印

優點

  1. 在不破壞物件封裝的情況下建立物件狀態快照。
  2. 可以方便地回到某個狀態。

缺點

  1. 每一次儲存物件狀態都會消耗一定的記憶體,隨著狀態增多,消耗的記憶體也會逐漸增多。
  2. 對於大物件的備份來說,備份和恢復的耗時會比較長。

何時使用

  1. 需要儲存/恢復資料的場景

實際應用場景

  1. 打遊戲時的存檔。
  2. Windows裡的ctrl + z。
  3. 瀏覽器中的後退。
  4. 資料庫的事務管理。
  5. 編輯器撤銷與重做。
  6. 虛擬機器生成快照與恢復。
  7. Git版本管理。
本作品採用《CC 協議》,轉載必須註明作者和本文連結
Long2Ge

相關文章