Maison  >  Article  >  développement back-end  >  Une brève discussion sur le modèle d'itérateur en PHP

Une brève discussion sur le modèle d'itérateur en PHP

青灯夜游
青灯夜游avant
2021-07-01 19:03:431430parcourir

Dans l'article précédent "Analyse approfondie du modèle d'observateur en PHP", nous avons présenté le modèle d'observateur en PHP. Cet article vous amènera à comprendre le modèle d'itérateur en PHP.

Une brève discussion sur le modèle d'itérateur en PHP

Quand il s'agit de ce modèle, nous devons mentionner les instructions de boucle. Dans « Dahua Design Pattern », l'auteur a déclaré que l'importance d'apprentissage de ce modèle est désormais supérieure à l'importance pratique. Pourquoi ? Bien sûr, c'était à cause de foreach. N'importe quel langage possède ce type de syntaxe similaire qui peut parcourir rapidement et facilement des tableaux et des objets, permettant ainsi au modèle d'itérateur de devenir lentement un passant de l'étoile parmi les 23 principaux modèles de conception. Surtout notre langage PHP, la puissance de PHP réside dans son fonctionnement flexible des tableaux. Il s'agit d'une structure de hashmap. Naturellement, il existe diverses syntaxes d'opération de tableau pratiques, et foreach est également notre instruction la plus couramment utilisée, encore meilleure que for. utilisé.

Diagramme de classes Gof et explication

Définition GoF : fournit une méthode pour accéder séquentiellement à chaque élément d'un objet agrégé sans exposer la représentation interne de l'objet

Diagramme de classes GoF

Une brève discussion sur le modèle ditérateur en PHP

Implémentation du code

interface Aggregate
{
    public function CreateIterator();
}

class ConcreteAggregate implements Aggregate
{
    public function CreateIterator()
    {
        $list = [
            "a",
            "b",
            "c",
            "d",
        ];
        return new ConcreteIterator($list);
    }
}

Le premier est la classe agrégée, qui est une classe qui peut être itérée Parce que je suis un modèle de conception orienté objet, le modèle itérateur vise à itérer le contenu d'une classe. Ici, en fait, nous avons simplement simulé un tableau et l'avons remis à l'itérateur.

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];
    }
}

L'itérateur fait ses débuts, et il implémente principalement quatre méthodes pour opérer sur les données de collecte. Un peu comme ce que l’on fait avec les curseurs lors de l’apprentissage de structures de données ou de bases de données. Utilisez First() et Next() pour déplacer le curseur, utilisez CurrentItem() pour obtenir le contenu des données du curseur actuel et utilisez IsDone() pour confirmer s'il existe des données suivantes. Par conséquent, ce mode est également appelé mode curseur.

$agreegate = new ConcreteAggregate();
$iterator = $agreegate->CreateIterator();

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

Le client peut directement utiliser while pour opérer.

  • Vous devez être curieux, pourquoi notre classe d'interface itérateur ne s'appelle-t-elle pas Iterator ? Essayez-le et vous saurez que PHP a préparé cette interface pour nous. Après l'avoir implémentée, vous pouvez utiliser foreach pour utiliser cette classe qui implémente l'interface Iterator. Voyons enfin l'utilisation de cette classe.
  • Tu n'as pas accepté de parcourir les cours ? Pourquoi passer un tableau d'avant en arrière ? Les étudiants ayant développé Java doivent savoir que dans un JavaBean nommé classe Object, une variable de type List, telle que List myList, est écrite pour représenter la collection actuelle d'objets. Après avoir ajouté des données à cette liste pendant l'utilisation, vous pouvez directement utiliser Object.myList pour obtenir un ensemble de données la prochaine fois. Par exemple, le contenu du tableau json obtenu à partir de l'interface peut être stocké dans un Bean. À l’heure actuelle, nous pouvons utiliser un itérateur pour opérer uniquement sur le tableau à l’intérieur de notre propre objet !
  • Le contenu Java ci-dessus est en fait ce que l'auteur utilise souvent lors du développement Android. Parfois, le JavaBean de la base de données aura également ce type de tableau pour stocker les clés étrangères. Mais il est généralement rarement utilisé en PHP, car la plupart des objets AR en PHP sont légèrement différents du concept Bean en Java. Les étudiants intéressés peuvent en apprendre davantage !

Notre usine de téléphones portables est incroyable. Nous avons nous-mêmes assemblé une ligne de production. À quoi sert principalement cette ligne de production ? Nous avons confié la machine de moulage à Fuji Kang et notre ligne est utilisée pour peindre des téléphones portables. Lorsque nous mettrons tous les téléphones portables livrés (Aggregate) dans différentes lignes de production (Iterator), ils nous aideront à peindre une par une la couleur de la ligne de production actuelle. ! La technologie ne consiste pas seulement à changer de coque. Si cette ligne est toujours là, nous pouvons faire d'autres choses, comme ajouter des longes. Quoi qu'il en soit, tant que je peux passer un par un, je peux mettre des choses. fonctionne-t-il ? Facile à utiliser ! !

Code complet : https://github.com/zhangyue0503/designpatterns-php/blob/master/07.iterator/source/iterator.php

实例

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

消息发送迭代器类图

Une brève discussion sur le modèle ditérateur en PHP

完整源码: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 = [
    &#39;13111111111&#39;,
    &#39;13111111112&#39;,
    &#39;13111111113&#39;,
    &#39;13111111114&#39;,
    &#39;13111111115&#39;,
    &#39;13111111116&#39;,
    &#39;13111111117&#39;,
    &#39;13111111118&#39;,
];

// 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视频教程

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer