一說到這個模式,就不得不提循環語句。在《大話設計模式》中,做者說道這個模式如今的學習意義更大於實際意義,這是爲何呢?固然就是被foreach這貨給整得。任何語言都有這種相似的語法能夠方便快捷的對數組、對象進行遍歷,從而讓迭代器模式從高高在上的23大設計模式中的明星慢慢成爲了路人。特別是咱們這門PHP語言,PHP的強大之處就在於對於數組的靈活操做,自己就是hashmap的結構,天然會有各類方便的數組操做語法,而foreach也是咱們最經常使用的語句,甚至比for還經常使用。php
GoF定義:提供一種方法順序訪問一個聚合對象中各個元素,而又不需暴露該對象的內部表示git
GoF類圖github
代碼實現面試
interface Aggregate { public function CreateIterator(); } class ConcreteAggregate implements Aggregate { public function CreateIterator() { $list = [ "a", "b", "c", "d", ]; return new ConcreteIterator($list); } }
首先是聚合類,也就是能夠進行迭代的類,這裏由於我是面向對象的設計模式,因此迭代器模式針對的是對一個類的內容進行迭代。在這裏,其實咱們也只是模擬了一個數組交給了迭代器。數據庫
interface MyIterator { public function First(); public function Next(); public function IsDone(); public function CurrentItem(); } class ConcreteIterator implements MyIterator { private $list; private $index; public function __construct($list) { $this->list = $list; $this->index = 0; } public function First() { $this->index = 0; } public function Next() { $this->index++; } public function IsDone() { return $this->index >= count($this->list); } public function CurrentItem() { return $this->list[$this->index]; } }
迭代器閃亮登場,主要實現了四個方法來對集合數據進行操做。有點像學習數據結構或數據庫時對遊標進行的操做。用First()和Next()來移動遊標,用CurrentItem()來得到當前遊標的數據內容,用IsDone()來確認是否還有下一條數據。因此,這個模式也另稱爲遊標模式。設計模式
$agreegate = new ConcreteAggregate(); $iterator = $agreegate->CreateIterator(); while (!$iterator->IsDone()) { echo $iterator->CurrentItem(), PHP_EOL; $iterator->Next(); }
客戶端直接使用while來進行操做便可。數組
咱們的手機工廠不得了,本身組裝了一條生產線,這條生產線主要是作什麼的呢?成型機咱們已經交給富X康來搞定了,咱們這條線就是給手機刷顏色的。當咱們把全部已經交貨的手機(Aggregate)放到不一樣的生產線後(Iterator),就會一臺一臺的幫咱們刷上當前生產線的顏色,是否是很強大!!科技不止於換殼,這條線還在,咱們就能夠再作別的事兒,好比加點掛繩什麼的,反正只要能一臺一臺的經過我就能裝上東西,你說好用很差用!!服務器
完整代碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/07.iterator/source/iterator.php微信
實例仍是圍繞着咱們的短信發送來看。這一次,咱們的業務需求是儘快的發一批通知短信給用戶,由於活動的時候可不等人啊。在以前咱們會使用多個腳原本把用戶手機號分紅多組來進行發送。如今咱們能夠用swoole來直接多線程的發送。所要達到的效果其實就是爲了快速的把成百上千的短信發完。這個時候咱們也會作一些策略,好比數據庫裏是100條要送的短信,有個字段是發送狀態,一個線程正序的發,一個線程倒序的發,當正序和倒序都發送到50條的時候其實已經同步的發完這100條了,不過也有可能會有失敗的狀況出現,這時,兩個線程還會繼續去發送那些上次發送不成功的信息,這樣可以最大程度的確保發送的效率和到達率。swoole
消息發送迭代器類圖
完整源碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/07.iterator/source/iterator-msg.php
<?php interface MsgIterator { public function First(); public function Next(); public function IsDone(); public function CurrentItem(); } // 正向迭代器 class MsgIteratorAsc implements MsgIterator { private $list; private $index; public function __construct($list) { $this->list = $list; $this->index = 0; } public function First() { $this->index = 0; } public function Next() { $this->index++; } public function IsDone() { return $this->index >= count($this->list); } public function CurrentItem() { return $this->list[$this->index]; } } // 反向迭代器 class MsgIteratorDesc implements MsgIterator { private $list; private $index; public function __construct($list) { // 反轉數組 $this->list = array_reverse($list); $this->index = 0; } public function First() { $this->index = 0; } public function Next() { $this->index++; } public function IsDone() { return $this->index >= count($this->list); } public function CurrentItem() { return $this->list[$this->index]; } } interface Message { public function CreateIterator($list); } class MessageAsc implements Message { public function CreateIterator($list) { return new MsgIteratorAsc($list); } } class MessageDesc implements Message { public function CreateIterator($list) { return new MsgIteratorDesc($list); } } // 要發的短信號碼列表 $mobileList = [ '13111111111', '13111111112', '13111111113', '13111111114', '13111111115', '13111111116', '13111111117', '13111111118', ]; // A服務器腳本或使用swoole發送正向的一半 $serverA = new MessageAsc(); $iteratorA = $serverA->CreateIterator($mobileList); while (!$iteratorA->IsDone()) { echo $iteratorA->CurrentItem(), PHP_EOL; $iteratorA->Next(); } // B服務器腳本或使用swoole同步發送反向的一半 $serverB = new MessageDesc(); $iteratorB = $serverB->CreateIterator($mobileList); while (!$iteratorB->IsDone()) { echo $iteratorB->CurrentItem(), PHP_EOL; $iteratorB->Next(); }
說明
完整源碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/06.observer/source/spl_observer.php
彩蛋
PHP中的Iterator接口已經爲咱們準備好了一套標準的Iterator模式的實現,並且(這裏須要畫重點),實現這個接口的類能夠用foreach來遍歷哦!
文檔:https://www.php.net/manual/zh/class.iterator.php
源碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/07.iterator/source/iterator-php.php
文檔中相關的接口均可以看看,更重要的是,PHP的SPL擴展中,也爲咱們準備了不少經常使用的迭代器封裝。要知道,面試的時候要是能說出這裏面的幾個來,那面試官但是也會另眼相看的哦!
SPL迭代器:https://www.php.net/manual/zh/spl.iterators.php
關注公衆號:【硬核項目經理】獲取最新文章
添加微信/QQ好友:【xiaoyuezigonggong/149844827】免費得PHP、項目管理學習資料
知乎、公衆號、抖音、頭條搜索【硬核項目經理】
B站ID:482780532