迭代器模式,并不在最初的23个设计模式中。但是,对于PHP,由于它的数组支持不同的数据类型,所以,PHP中少了很多静态数据类型。并且,forech的强大,以致于初级用户想不到使用迭代器模式。
迭代器模式,PHP提供了多种实现方式。其一是SPL。
在SPL中,我们有:Countable, ArrayAccess, Iterator 这三个接口。通过这三个接口,我们可以把一个类,当成数组来使用。这是最简单的迭代器模式。(大家可以查一下PHP手册中关于Countable, ArrayAccess, Iterator的例子)
有人要问,为什么要用迭代器模式呢?道理很简单,如果你的foreach中的代码很长,并且,多个这样的代码且很多类似的地方。那么,你就可以用类的方式来实现,从而把具体的放到类中,通过继承实现具体的算法。
比如,下面一个例子,是生成一组 YYYY-MM-DD 的键值,从而到查询结查中获取对应的数据。用这个类,封装了KEY的生成。此类中实现的就是SPL的Iterator接口
namespace MyData\Models\Iterators; use Carbon\Carbon; use Iterator; /** * Class KeyIterator * @package MyData\Models\Iterators */ class KeyIterator implements Iterator { /** * Order type of array * 顺序:下一条记录,加1 */ const ORDER_ASC = 1; /** * Order type of array * 倒序:上一条记录,减1 */ const ORDER_DESC = -1; /** * 用于生成数组KEY的data format */ const DATE_FORMAT = 'Y-m-d'; /** @var Carbon */ private $keyDate; /** * @var */ private $orderType; /** * @var */ private $itemCount; /** * @var */ private $position; /** * @var int * * 是否显示最近一个月,默认不显示, * 因为,当前月份一般可能是没有数据!! * */ private $showRecent = 0; /** * KeyIterator constructor. * @param $orderType * @param int $itemCount */ private function __construct($orderType,$itemCount=132) { $this->orderType = $orderType; $this->itemCount = $itemCount; } /** * @param $orderBy * @param $itemCount * @return static */ public static function of($orderBy,$itemCount){ return new static($orderBy,$itemCount); } /** * @return int */ public function count(){ return $this->itemCount; } private function reset() { $this->keyDate = now()->setDay(1)->subMonths($this->itemCount-$this->showRecent); } private function end(){ $this->keyDate = now()->setDay(1)->subMonths(abs($this->showRecent-1)); } /** * @return mixed */ public function rewind() { $this->position = 0; if(self::ORDER_ASC === $this->orderType){ $this->reset(); }else{ $this->end(); } return $this->keyDate->format(self::DATE_FORMAT); } /** * @return mixed */ public function current() { return $this->keyDate->format(self::DATE_FORMAT); } /** * @return mixed */ public function key() { return $this->position; } /** * @return mixed */ public function next() { $this->position++; if($this->position >= $this->itemCount){ return false; } if(self::ORDER_ASC === $this->orderType){ $this->keyDate = $this->keyDate->addMonth(); }else{ $this->keyDate = $this->keyDate->subMonth(); } return $this->keyDate->format(self::DATE_FORMAT); } /** * @return mixed */ public function prev(){ $this->position--; if($this->position < 0){ return false; } if(self::ORDER_ASC === $this->orderType){ $this->keyDate = $this->keyDate->subMonth(); }else{ $this->keyDate = $this->keyDate->addMonth(); } return $this->keyDate->format(self::DATE_FORMAT); } /** * @return bool */ public function valid() { return $this->position<$this->itemCount; } }
有了上面这个类,我们就可以:
$keyItems = KeyIterator::of($this->orderType,$this->fetchCount); //上面是迭代器对象,所以,直接用foreach foreach($keyItems as $key => $itemKey){ //直接用生成的$itemKey去读取源数据 $outArray[$key] = $sourceArray[$itemKey] }
迭代器,可以帮助我们把具体的算法放到类中,从而可以使代码可读性增强,且使得代码可维护。
同样,迭代器模式,还能让我们的减少使用foreach。这是因为,我们可以通过类的结构,把算法结构化。
现在,PHP中又增加了yield这个生成器函数。使得迭代器模式变得更加方便。
比如,我们要做一个环形双向链表。当然,有人会问,这个有什么用?
其实,用到的地方还是很多的。比如, 我们在WINDWS任务管理器中,能够看到动态显示的性能图表。这个图表,如果用环形链表,就相当方便。
再如,涉及地理多边形计算时,我们也需要用到环形链表。
这里我们推荐一个环形链表开源。是基于yield实现的。
此组件拥有以下特性:
- 支持带接头的数组。比如地理数据多边形就有接头,最后一个元素与第一个是相同的。最后一个就是接头。
- 支持元素更新,查找,插入,移除,添加等操作。
- 支持顺序迭代 nextItems() 与逆序迭代 prevItems(),
- 支持多圈迭代 nextItemsWithCount() prevItemsWithCout(),
- 支持任意整数的开始位置与结束位置
- 具有双向链表完全特性,可以通过,nextItem()和prevItem() 获取前一元素以下后面元素。nextKey()和prevKey() 获以前一元素和后一元素的Key
- 支持队列所需的特性,具有push,pop,shift,unshift操作,且队列也支持接头
项目地址: https://github.com/BardoQi/circular-linked-list
这个项目,仅有一个类。且连注解在内,整个类只有400行。我们不得不感叹PHP语言的强大。它不需要复杂的数据结构,但当我们需要使用时,我们可以用极简的代码实现我们所要的数据结构的类。相比JAVA, C++, 这些语言,你要了解 ArrayList, TreeMap , HashMap, Vertor, ...等一堆数据结构,PHP确实简单且方便多了。
相关推荐
在实际应用中,迭代器模式常用于各种容器(如数组、链表、树等)的遍历,以及模板方法模式、策略模式等设计模式的组合。例如,在Java的`Collections`类中,有许多方法(如`sort()`、`shuffle()`)都依赖于迭代器来...
迭代器模式是一种设计模式,它在软件工程中扮演着重要的角色,特别是在处理集合或容器类对象的遍历操作时。这种模式提供了一种方法来顺序访问聚合对象的元素,而无需暴露其底层表示。在Java、C#等面向对象语言中,...
3. **灵活性与可扩展性**:迭代器模式支持在不改变聚合类及其客户端的情况下,提供新的迭代器类,增加新的遍历方式。 ### 迭代器模式的代码实现 在实现迭代器模式时,首先要定义迭代器接口,包括获取下一个元素和...
迭代器模式是一种行为设计模式,它允许我们顺序访问聚合对象的元素,而无需暴露其底层表示。在Java、C#等面向对象编程语言中,迭代器模式被广泛应用于集合类库,如ArrayList、LinkedList等。这个"迭代器模式demo...
迭代器模式是软件设计模式中的一种行为模式,它允许我们顺序访问聚合对象的元素,而无需暴露其底层表示。在Java、C#等面向对象语言中,迭代器模式被广泛应用于容器类,如ArrayList、LinkedList等,使得我们可以方便...
同时,迭代器模式也可以与其他设计模式结合使用,如工厂模式用于创建迭代器实例,或者装饰者模式用于添加新的遍历行为。 总之,迭代器模式是软件设计中一种非常实用的模式,它为遍历聚合对象提供了一种标准接口,...
迭代器模式是一种设计模式,属于行为设计模式,它允许我们顺序访问聚合对象的元素,而无需暴露其底层表示。在Java、C#等面向对象语言中,迭代器模式被广泛应用于容器类,如ArrayList、LinkedList等,使得我们可以...
迭代器模式是软件设计模式中的一种行为模式,它在C#等面向对象编程语言中有着广泛的应用。这个模式的主要目标是允许用户遍历一个聚合对象(如数组、集合或列表)的所有元素,而无需了解底层的实现细节。下面将详细...
迭代器模式是一种行为设计模式,它提供了一种方法来顺序访问聚合对象的元素,而无需暴露其底层表示。这种模式允许我们遍历集合中的每个元素,同时保持集合本身抽象,不需了解其内部结构。 在Java、C#等面向对象语言...
在这个主题中,我们主要探讨了如何利用组合模式(Composite Pattern)构建二叉树,并通过迭代器模式(Iterator Pattern)来实现对树的遍历,包括前序、中序和后序遍历。这些是设计模式中的经典应用,对于理解和掌握...
总的来说,Headfirst的第九章通过迭代器模式的讲解,让读者了解如何在C++中使用这种模式,同时通过UML类图帮助理解类与类之间的关系,使得设计模式的学习更加直观易懂。掌握迭代器模式,对于编写高效、可维护的代码...
迭代器模式是一种行为设计模式,主要目的是在不暴露集合内部结构的情况下,允许外部代码遍历集合的所有元素。这种模式将遍历操作从集合类中分离出来,实现了数据结构和遍历机制的解耦。在大多数编程语言中,迭代器...
迭代器模式(Iterator Pattern)是Java设计模式中的行为模式之一,它提供了一种方法来顺序访问聚合对象的元素,而又不暴露其底层表示。在Java中,迭代器模式被广泛应用于集合类,如ArrayList、LinkedList等,通过...
### (行为型模式) Iterator 迭代器模式 #### 概述 在软件工程领域,设计模式被广泛应用于解决常见的编程问题。其中,“迭代器模式”作为一种行为型设计模式,在处理集合类对象时发挥着重要作用。本文将详细介绍...
迭代器模式是软件设计模式中的一种行为模式,它允许我们顺序访问聚合对象的元素,而无需暴露其底层表示。在“设计模式之迭代器模式(新)”中,我们将深入探讨这种模式的核心概念、实现方式以及它在实际编程中的应用...
7. **迭代器模式与foreach循环**:Java 5引入的增强for循环(也称为foreach循环),底层就是迭代器模式的实现。例如: ```java for (Type element : collection) { // 处理element } ``` 这样的代码简洁且易于...
迭代器模式是一种行为设计模式,它允许我们顺序访问聚合对象的元素,而无需暴露其底层表示。在Java中,迭代器模式广泛应用于集合框架,如ArrayList、LinkedList等。本示例将深入探讨如何在Java中实现和使用迭代器...