在先前的文章《深入淺析PHP中的建造者模式》中我們介紹了PHP中的建造者模式,以下這篇文章帶大家了解一下PHP設計模式中的備忘錄模式。
備忘錄,這個名字其實已經很形象的解釋了它的作用。典型的例子就是我們原來玩硬碟遊戲時的存檔功能。當你對即將面對的大BOSS有所顧慮時,一般都會先保存一次進度存檔。如果挑戰失敗了,直接讀取存檔就可以恢復到挑戰BOSS前的狀態,然後你就開開心心的再去練一會級回來解決這個大BOSS就好了。不過,為了以防萬一,在挑戰BOSS之前就先存檔總是好的。另外一個例子就是我們碼農們天天要用到的程式碼管理工具Git或Svn了。每次的提交都像是存檔備份,當新程式碼出現問題的時候,直接回溯恢復就行了。這些,都是備忘錄模式的典型應用,以下就一起來看看這個模式吧。
Gof類別圖及解釋
GoF定義:在不破壞封裝性的前提下,捕捉一個物件的內部狀態,並在該物件之外保存這個狀態。這樣以後就可將該物件還原到原先儲存的狀態
GoF類別圖:
程式碼實作:
class Originator { private $state; public function SetMeneto(Memento $m) { $this->state = $m->GetState(); } public function CreateMemento() { $m = new Memento(); $m->SetState($this->state); return $m; } public function SetState($state) { $this->state = $state; } public function ShowState() { echo $this->state, PHP_EOL; } }
原發器,也可以叫做發起人。它有一個內部狀態(state),這個狀態可以在不同的情況下進行改變。當某一個事件發生時,需要將這個狀態恢復到原先的狀態。在這裡,我們有一個CreateMemento()用於建立一個備忘錄(存檔),有一個SetMeneto()用於還原狀態(讀檔)。
class Memento { private $state; public function SetState($state) { $this->state = $state; } public function GetState() { return $this->state; } }
備忘錄,非常簡單,就是用來記錄狀態。將這個狀態以物件的形式保存,就可以讓原發器非常方便地建立許多存檔用來記錄各種不同的狀態。
class Caretaker { private $memento; public function SetMemento($memento) { $this->memento = $memento; } public function GetMemento() { return $this->memento; } }
負責人,也叫做管理者類,保存備忘錄,當需要的時候從這裡取出備忘錄。它只負責保存,不能修改備忘錄。在複雜的應用中,可以將這裡做成列表,就像遊戲中可以選擇性的展現多條存檔記錄供玩家選擇。
$o = new Originator(); $o->SetState('状态1'); $o->ShowState(); // 保存状态 $c = new Caretaker(); $c->SetMemento($o->CreateMemento()); $o->SetState('状态2'); $o->ShowState(); // 还原状态 $o->SetMeneto($c->GetMemento()); $o->ShowState();
客戶端的呼叫中,我們的原發器初始化狀態後進行了保存,然後人為的更改了狀態。這時只需要透過負責人將狀態還原回來就可以了。
- 備忘錄模式說白了就是讓一個外部類別B來保存A的內部狀態,然後在適當的時候可以方便的還原這個狀態。
- 備忘錄模式的應用場景其實非常多,瀏覽器的回退、資料庫的備份還原、作業系統的備份還原、文件的撤銷重做、棋牌遊戲的悔棋等等
- 這個模式能夠保持原發器的封裝,也就是這些狀態需要對外部的物件隱藏,所以只能交給一個備忘錄物件來記錄
- 狀態在原發器和備忘錄之間的拷貝可能帶來效能問題,特別是大型物件的複雜繁多的內部狀態,而且也會帶來一些編碼方面的漏洞,例如遺漏某些狀態
##Mac的時光機功能大家有了解吧,可以將電腦恢復到某個時間點的狀態。其實windows的ghost也是類似的功能。我們的手機作業系統上也決定開發這樣的一個功能。當我們點擊時光機備份時,將手機上所有的資料、數據、狀態資訊都壓縮保存起來,如果用戶允許的話,我們將這個壓縮包上傳到我們的雲端伺服器上避免佔用用戶的手機內存,否則就只能儲存到用戶的手機內存了。當用戶的手機需要恢復到某個時間點,我們將所有的時光機備份列出,用戶只需要用手指輕輕一按就可以把手機系統狀態恢復到當時的樣子了,是不是非常方便! !
完整程式碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/17.memento/source/memento.php
#實例
這次又回到簡訊發送的範例。通常我們做簡訊或郵件發送這些功能時,會有一個佇列從資料庫或快取中讀取要傳送的內容進行傳送,如果成功了就不管了,如果失敗了會將簡訊的狀態改成失敗或重發。在這裡,我們直接將它改回到之前未發送的狀態然後等待下次發送的佇列再次執行發送。簡訊發送類別圖
#完整原始碼:https://github.com/zhangyue0503/designpatterns-php /blob/master/17.memento/source/memento-message.php
<?php class Message { private $content; private $to; private $state; private $time; public function __construct($to, $content) { $this->to = $to; $this->content = $content; $this->state = '未发送'; $this->time = time(); } public function Show() { echo $this->to, '---', $this->content, '---', $this->time, '---', $this->state, PHP_EOL; } public function CreateSaveSate() { $ss = new SaveState(); $ss->SetState($this->state); return $ss; } public function SetSaveState($ss) { if ($this->state != $ss->GetState()) { $this->time = time(); } $this->state = $ss->GetState(); } public function SetState($state) { $this->state = $state; } public function GetState() { return $this->state; } } class SaveState { private $state; public function SetState($state) { $this->state = $state; } public function GetState() { return $this->state; } } class StateContainer { private $ss; public function SetSaveState($ss) { $this->ss = $ss; } public function GetSaveState() { return $this->ss; } } // 模拟短信发送 $mList = []; $scList = []; for ($i = 0; $i < 10; $i++) { $m = new Message('手机号' . $i, '内容' . $i); echo '初始状态:'; $m->Show(); // 保存初始信息 $sc = new StateContainer(); $sc->SetSaveState($m->CreateSaveSate()); $scList[] = $sc; // 模拟短信发送,2发送成功,3发送失败 $pushState = mt_rand(2, 3); $m->SetState($pushState == 2 ? '发送成功' : '发送失败'); echo '发布后状态:'; $m->Show(); $mList[] = $m; } // 模拟另一个线程查找发送失败的并把它们还原到未发送状态 sleep(2); foreach ($mList as $k => $m) { if ($m->GetState() == '发送失败') { // 如果是发送失败的,还原状态 $m->SetSaveState($scList[$k]->GetSaveState()); } echo '查询发布失败后状态:'; $m->Show(); }
说明
- 短信类做为我们的原发器,在发送前就保存了当前的发送状态
- 随机模拟短信发送,只有两个状态,发送成功或者失败,并改变原发器的状态为成功或者失败
- 模拟另一个线程或者脚本对短信的发送状态进行检查,如果发现有失败的,就将它重新改回未发送的状态
- 这里我们只是保存了发送状态这一个字段,其他原发器的内部属性并没有保存
- 真实的场景下我们应该会有一个重试次数的限制,当超过这个次数后,状态改为彻底的发送失败,不再进行重试了
原文地址:https://juejin.cn/post/6844903983555805192
作者:硬核项目经理
推荐学习:《PHP视频教程》
以上是一起聊聊PHP中的備忘錄模式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

phpIdentifiesauser'ssessionSessionSessionCookiesAndSessionId.1)whiwsession_start()被稱為,phpgeneratesainiquesesesessionIdStoredInacookInAcookInAcienamedInAcienamedphpsessIdontheuser'sbrowser'sbrowser.2)thisIdallowSphptpptpptpptpptpptpptpptoretoreteretrieetrieetrieetrieetrieetrieetreetrieetrieetrieetrieetremthafromtheserver。

PHP會話的安全可以通過以下措施實現:1.使用session_regenerate_id()在用戶登錄或重要操作時重新生成會話ID。 2.通過HTTPS協議加密傳輸會話ID。 3.使用session_save_path()指定安全目錄存儲會話數據,並正確設置權限。

phpsessionFilesArestoredIntheDirectorySpecifiedBysession.save_path,通常是/tmponunix-likesystemsorc:\ windows \ windows \ temponwindows.tocustomizethis:tocustomizEthis:1)useession_save_save_save_path_path()

ToretrievedatafromaPHPsession,startthesessionwithsession_start()andaccessvariablesinthe$_SESSIONarray.Forexample:1)Startthesession:session_start().2)Retrievedata:$username=$_SESSION['username'];echo"Welcome,".$username;.Sessionsareserver-si

利用會話構建高效購物車系統的步驟包括:1)理解會話的定義與作用,會話是服務器端的存儲機制,用於跨請求維護用戶狀態;2)實現基本的會話管理,如添加商品到購物車;3)擴展到高級用法,支持商品數量管理和刪除;4)優化性能和安全性,通過持久化會話數據和使用安全的會話標識符。

本文討論了PHP中的crypt()和password_hash()的差異,以進行密碼哈希,重點介紹其實施,安全性和對現代Web應用程序的適用性。

文章討論了通過輸入驗證,輸出編碼以及使用OWASP ESAPI和HTML淨化器之類的工具來防止PHP中的跨站點腳本(XSS)。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

SublimeText3 Linux新版
SublimeText3 Linux最新版

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

SublimeText3漢化版
中文版,非常好用

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。