GoF类图

迭代器模式

代码实现

php迭代器PHP设计模式之迭代器模式 Vue.js

interfaceAggregate{publicfunctionCreateIterator();}classConcreteAggregateimplementsAggregate{publicfunctionCreateIterator(){$list=["a","b","c","d",];returnnewConcreteIterator($list);}}

首先是聚合类,也便是可以进行迭代的类,这里由于我是面向工具的设计模式,以是迭代器模式针对的是对一个类的内容进行迭代。
在这里,实在我们也只是仿照了一个数组交给了迭代器。

interfaceMyIterator{publicfunctionFirst();publicfunctionNext();publicfunctionIsDone();publicfunctionCurrentItem();}classConcreteIteratorimplementsMyIterator{private$list;private$index;publicfunction__construct($list){$this->list=$list;$this->index=0;}publicfunctionFirst(){$this->index=0;}publicfunctionNext(){$this->index++;}publicfunctionIsDone(){return$this->index>=count($this->list);}publicfunctionCurrentItem(){return$this->list[$this->index];}}

迭代器闪亮登场,紧张实现了四个方法来对凑集数据进行操作。
有点像学习数据构造或数据库时对游标进行的操作。
用First()和Next()来移动游标,用CurrentItem()来获得当前游标的数据内容,用IsDone()来确认是否还有下一条数据。
以是,这个模式也另称为游标模式。

$agreegate=newConcreteAggregate();$iterator=$agreegate->CreateIterator();while(!$iterator->IsDone()){echo$iterator->CurrentItem(),PHP_EOL;$iterator->Next();}

客户端直策应用while来进行操作即可。

大家一定很好奇,为什么我们的迭代器接口类不用Iterator来命名?试试就知道,PHP为我们准备好了一个这个接口,实现之后就可以用foreach来利用这个实现了Iterator接口的类了,是不是很高大上。
我们末了再看这个类的利用。
不是说好对类进行遍历吗?为啥来回通报一个数组?开拓过Java的同学一定知道,在一个名为Object类的JavaBean中,会写一个变量List<Object>类型的变量如List<Object> myList,用来表示当前工具的凑集。
在利用的时候给这个List添加数据后,下次就可以直接用Object.myList来得到一组数据了。
比如从接口中得到的json数组内容就可以这样存在一个Bean中。
这时,我们利用迭代器就可以只针对自己这个工具内部的这个数组来进行操作啦!
上述Java的内容实在是笔者在做Android开拓时常常会用到的,有时数据库的JavaBean也会涌现这种数组来存储外键。
但在PHP中一样平常很少利用,由于PHP中大部分的AR工具和Java中的Bean观点还是略有不同。
有兴趣的同学可以理解下!

我们的手机工厂不得了,自己组装了一条生产线,这条生产线紧张是做什么的呢?成型机我们已经交给富X康来搞定了,我们这条线便是给手机刷颜色的。
当我们把所有已经交货的手机(Aggregate)放到不同的生产线后(Iterator),就会一台一台的帮我们刷上当前生产线的颜色,是不是很强大!

科技不止于换壳,这条线还在,我们就可以再做别的事儿,比如加点挂绳什么的,反正只要能一台一台的通过我就能装上东西,你说好用不好用!

完全代码:https://github.com/zhangyue0503/designpatterns-php/blob/master/07.iterator/source/iterator.php

实例

实例还是环绕着我们的短信发送来看。
这一次,我们的业务需求是尽快的发一批关照短信给用户,由于活动的时候可不等人啊。
在之前我们会利用多个脚本来把用户手机号分成多组来进行发送。
现在我们可以用swoole来直接多线程的发送。
所要达到的效果实在便是为了快速的把成百上千的短信发完。
这个时候我们也会做一些策略,比如数据库里是100条要送的短信,有个字段是发送状态,一个线程正序的发,一个线程倒序的发,当正序和倒序都发送到50条的时候实在已经同步的发完这100条了,不过也有可能会有失落败的情形涌现,这时,两个线程还会连续去发送那些上次发送不堪利的信息,这样能够最大程度的确保发送的效率和到达率。

发送迭代器类图

发送迭代器

完全源码:https://github.com/zhangyue0503/designpatterns-php/blob/master/07.iterator/source/iterator-msg.php

<?phpinterfaceMsgIterator{publicfunctionFirst();publicfunctionNext();publicfunctionIsDone();publicfunctionCurrentItem();}//正向迭代器classMsgIteratorAscimplementsMsgIterator{private$list;private$index;publicfunction__construct($list){$this->list=$list;$this->index=0;}publicfunctionFirst(){$this->index=0;}publicfunctionNext(){$this->index++;}publicfunctionIsDone(){return$this->index>=count($this->list);}publicfunctionCurrentItem(){return$this->list[$this->index];}}//反向迭代器classMsgIteratorDescimplementsMsgIterator{private$list;private$index;publicfunction__construct($list){//反转数组$this->list=array_reverse($list);$this->index=0;}publicfunctionFirst(){$this->index=0;}publicfunctionNext(){$this->index++;}publicfunctionIsDone(){return$this->index>=count($this->list);}publicfunctionCurrentItem(){return$this->list[$this->index];}}interfaceMessage{publicfunctionCreateIterator($list);}classMessageAscimplementsMessage{publicfunctionCreateIterator($list){returnnewMsgIteratorAsc($list);}}classMessageDescimplementsMessage{publicfunctionCreateIterator($list){returnnewMsgIteratorDesc($list);}}//要发的短旗子暗记码列表$mobileList=['13111111111','13111111112','13111111113','13111111114','13111111115','13111111116','13111111117','13111111118',];//A做事器脚本或利用swoole发送正向的一半$serverA=newMessageAsc();$iteratorA=$serverA->CreateIterator($mobileList);while(!$iteratorA->IsDone()){echo$iteratorA->CurrentItem(),PHP_EOL;$iteratorA->Next();}//B做事器脚本或利用swoole同步发送反向的一半$serverB=newMessageDesc();$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

下期看点

迭代器很好玩吧,而且和不雅观察者一样,PHP本身的扩展库竟然为我们准备了很多接口。
平常写代码的时候是不是可以炫炫技了呢!

别急,我们进入设计模式的天下并不久,还有很多故意思的设计模式等着我们去学习,就像原型模式,这货干嘛的?复制自己哦,克隆人的战役!