它提供了在不破壞封裝(對象不須要具備返回當前狀態的函數)的狀況下恢復到以前狀態(使用回滾)或者獲取對象的內部狀態。php
備忘錄模式使用 3 個類來實現:Originator,Caretaker 和 Memento。laravel
Memento —— 負責存儲 Originator 的 惟一內部狀態 ,它能夠包含: string,number, array,類的實例等等。Memento 「不是公開的類」(任何人都不該該且不能更改它),並防止 Originator 之外的對象訪問它,它提供 2 個接口:Caretaker 只能看到備忘錄的窄接口,他只能將備忘錄傳遞給其餘對象。Originator 卻可看到備忘錄的寬接口,容許它訪問返回到先前狀態所須要的全部數據。面試
Originator —— 它負責建立 Memento ,並記錄 外部對象當前時刻的狀態, 並可以使用 Memento 恢復內部狀態。Originator 可根據須要決定 Memento 存儲 Originator 的哪些內部狀態。 Originator 也許(不是應該)有本身的方法(methods)。 可是,他們 不能更改已保存對象的當前狀態。sql
Caretaker —— 負責保存 Memento。 它能夠修改一個對象;決定 Originator 中對象當前時刻的狀態; 從 Originator 獲取對象的當前狀態; 或者回滾 Originator 中對象的狀態。shell
保存以前控制 ORM Model 中的狀態設計模式
並將這個隨機數存在時序機中服務器
發送一個隨機數架構
<?php namespace DesignPatterns\Behavioral\Memento; class Memento { /** * @var State */ private $state; /** * @param State $stateToSave */ public function __construct(State $stateToSave) { $this->state = $stateToSave; } /** * @return State */ public function getState() { return $this->state; } }
<?php namespace DesignPatterns\Behavioral\Memento; class State { const STATE_CREATED = 'created'; const STATE_OPENED = 'opened'; const STATE_ASSIGNED = 'assigned'; const STATE_CLOSED = 'closed'; /** * @var string */ private $state; /** * @var string[] */ private static $validStates = [ self::STATE_CREATED, self::STATE_OPENED, self::STATE_ASSIGNED, self::STATE_CLOSED, ]; /** * @param string $state */ public function __construct(string $state) { self::ensureIsValidState($state); $this->state = $state; } private static function ensureIsValidState(string $state) { if (!in_array($state, self::$validStates)) { throw new \InvalidArgumentException('Invalid state given'); } } public function __toString(): string { return $this->state; } }
<?php namespace DesignPatterns\Behavioral\Memento; /** * Ticket 是 Originator 的原始副本 */ class Ticket { /** * @var State */ private $currentState; public function __construct() { $this->currentState = new State(State::STATE_CREATED); } public function open() { $this->currentState = new State(State::STATE_OPENED); } public function assign() { $this->currentState = new State(State::STATE_ASSIGNED); } public function close() { $this->currentState = new State(State::STATE_CLOSED); } public function saveToMemento(): Memento { return new Memento(clone $this->currentState); } public function restoreFromMemento(Memento $memento) { $this->currentState = $memento->getState(); } public function getState(): State { return $this->currentState; } }
<?php namespace DesignPatterns\Behavioral\Memento\Tests; use DesignPatterns\Behavioral\Memento\State; use DesignPatterns\Behavioral\Memento\Ticket; use PHPUnit\Framework\TestCase; class MementoTest extends TestCase { public function testOpenTicketAssignAndSetBackToOpen() { $ticket = new Ticket(); // 打開 ticket $ticket->open(); $openedState = $ticket->getState(); $this->assertEquals(State::STATE_OPENED, (string) $ticket->getState()); $memento = $ticket->saveToMemento(); // 分配 ticket $ticket->assign(); $this->assertEquals(State::STATE_ASSIGNED, (string) $ticket->getState()); // 如今已經恢復到已打開的狀態,但須要驗證是否已經克隆了當前狀態做爲副本 $ticket->restoreFromMemento($memento); $this->assertEquals(State::STATE_OPENED, (string) $ticket->getState()); $this->assertNotSame($openedState, $ticket->getState()); } }
PHP 互聯網架構師 50K 成長指南+行業問題解決總綱(持續更新)
面試10家公司,收穫9個offer,2020年PHP 面試問題
★若是喜歡個人文章,想與更多資深開發者一塊兒交流學習的話,獲取更多大廠面試相關技術諮詢和指導,歡迎加入咱們的羣啊,暗號:phpzh(君羊號碼856460874)。
內容不錯的話但願你們支持鼓勵下點個贊/喜歡,歡迎一塊兒來交流;另外若是有什麼問題 建議 想看的內容能夠在評論提出