이전 기사 "PHP의 관찰자 패턴 심층 분석"에서 PHP의 관찰자 패턴을 소개했습니다. 이 기사에서는 PHP의 반복자 패턴을 이해하는 데 도움이 됩니다.
이 패턴에 관해서는 루프 문을 언급해야 합니다. "Dahua 디자인 패턴"에서 저자는 이 모델의 학습 중요성이 이제 실제적인 중요성보다 크다고 말했습니다. 물론 foreach 때문이었습니다. 모든 언어에는 배열과 객체를 빠르고 쉽게 탐색할 수 있는 이와 유사한 구문이 있으므로 반복자 패턴이 23개의 주요 디자인 패턴 중 별에서 천천히 지나가는 사람이 될 수 있습니다. 특히 PHP 언어의 강점은 해시맵 구조입니다. 당연히 다양한 편리한 배열 연산 구문이 있으며 foreach는 for보다 훨씬 더 일반적으로 사용되는 구문이기도 합니다. 사용된.
GoF 정의: 객체의 내부 표현을 노출하지 않고 집계 객체의 각 요소에 순차적으로 액세스하는 방법을 제공합니다.
GoF 클래스 다이어그램
코드 구현
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(); }
클라이언트가 작동하는 동안 직접 사용할 수 있습니다.
우리 휴대폰 공장은 정말 대단합니다. 우리가 직접 생산 라인을 조립했습니다. 이 생산 라인은 주로 어떤 용도로 사용되나요? 성형기를 강후지씨에게 넘겨주었으며, 당사 라인은 휴대폰 도장에 사용되고 있습니다. 납품된 휴대폰(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
<?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
本文转载自:https://juejin.cn/post/6844903937921777671
作者:硬核项目经理
推荐学习:《PHP视频教程》
위 내용은 PHP의 반복자 패턴에 대한 간략한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!