目的
它提供了在不破壞封裝(物件不需要具有回傳當前狀態的函式)的情況下恢復到之前狀態(使用回滾)或者獲取物件的內部狀態,
備忘錄模式使用 3 個類來實作:Originator,Caretaker 和 Memento,
Memento —— 負責存盤 Originator 的 唯一內部狀態 ,它可以包含: string,number, array,類的實體等等,Memento 「不是公開的類」(任何人都不應該且不能更改它),并防止 Originator 以外的物件訪問它,它提供 2 個介面:Caretaker 只能看到備忘錄的窄介面,他只能將備忘錄傳遞給其他物件,Originator 卻可看到備忘錄的寬介面,允許它訪問回傳到先前狀態所需要的所有資料,
Originator —— 它負責創建 Memento ,并記錄 外部物件當前時刻的狀態, 并可使用 Memento 恢復內部狀態,Originator 可根據需要決定 Memento 存盤 Originator 的哪些內部狀態, Originator 也許(不是應該)有自己的方法(methods), 但是,他們 不能更改已保存物件的當前狀態,
Caretaker —— 負責保存 Memento, 它可以修改一個物件;決定 Originator 中物件當前時刻的狀態; 從 Originator 獲取物件的當前狀態; 或者回滾 Originator 中物件的狀態,
例子
-
保存之前控制 ORM Model 中的狀態
-
并將這個亂數存在時序機中
-
發送一個亂數
UML圖

★官方PHP高級學習交流社群「點擊」管理整理了一些資料,BAT等一線大廠進階知識體系備好(相關學習資料以及筆面試題)以及不限于:分布式架構、高可擴展、高性能、高并發、服務器性能調優、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql優化、shell腳本、Docker、微服務、Nginx等多個知識點高級進階干貨
代碼
- Memento.php
<?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;
}
}
- State.php
<?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;
}
}
- Ticket.php
<?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;
}
}
測驗
- Tests/MementoTest.php
<?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 互聯網架構師成長之路*「設計模式」終極指南
PHP 互聯網架構師 50K 成長指南+行業問題解決總綱(持續更新)
面試10家公司,識訓9個offer,2020年PHP 面試問題
★如果喜歡我的文章,想與更多資深開發者一起交流學習的話,獲取更多大廠面試相關技術咨詢和指導,歡迎加入我們的群啊,暗號:phpzh(君羊號碼856460874),
2020年最新PHP進階教程,全系列!

內容不錯的話希望大家支持鼓勵下點個贊/喜歡,歡迎一起來交流;另外如果有什么問題 建議 想看的內容可以在評論提出
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/76707.html
標籤:PHP
