Heim  >  Artikel  >  Backend-Entwicklung  >  Eine kurze Diskussion des Iteratormusters in PHP

Eine kurze Diskussion des Iteratormusters in PHP

青灯夜游
青灯夜游nach vorne
2021-07-01 19:03:431430Durchsuche

Im vorherigen Artikel „Eingehende Analyse des Beobachtermusters in PHP“ haben wir das Beobachtermuster in PHP vorgestellt. Dieser Artikel führt Sie zum Verständnis des Iteratormusters in PHP.

Eine kurze Diskussion des Iteratormusters in PHP

Wenn es um dieses Muster geht, müssen wir Schleifenanweisungen erwähnen. In „Dahua Design Pattern“ sagte der Autor, dass die Lernbedeutung dieses Modells jetzt größer ist als die praktische Bedeutung. Natürlich lag es an foreach. Jede Sprache verfügt über eine ähnliche Syntax, die Arrays und Objekte schnell und einfach durchqueren kann, sodass das Iteratormuster langsam vom Stern unter den 23 wichtigsten Entwurfsmustern abweicht. Insbesondere in unserer PHP-Sprache liegt die Stärke von PHP in der flexiblen Array-Operation. Natürlich gibt es verschiedene praktische Array-Operationssyntaxen, und foreach ist auch unsere am häufigsten verwendete Anweisung, sogar besser als for gebraucht.

Gof-Klassendiagramm und Erklärung

GoF-Definition: Bietet eine Methode für den sequentiellen Zugriff auf jedes Element in einem Aggregatobjekt, ohne die interne Darstellung des Objekts offenzulegen

GoF-Klassendiagramm

Eine kurze Diskussion des Iteratormusters in PHP

Code-Implementierung

interface Aggregate
{
    public function CreateIterator();
}

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

Die erste ist die Aggregatklasse, eine Klasse, die iteriert werden kann. Da ich ein objektorientiertes Entwurfsmuster bin, zielt das Iteratormuster darauf ab, den Inhalt einer Klasse zu iterieren. Hier haben wir tatsächlich nur ein Array simuliert und es dem Iterator übergeben.

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

Der Iterator feiert sein Debüt und implementiert hauptsächlich vier Methoden für die Bearbeitung von Sammlungsdaten. Ein bisschen so, wie man es mit Cursorn macht, wenn man Datenstrukturen oder Datenbanken lernt. Verwenden Sie First() und Next(), um den Cursor zu bewegen, verwenden Sie CurrentItem(), um den Dateninhalt des aktuellen Cursors abzurufen, und verwenden Sie IsDone(), um zu bestätigen, ob nächste Daten vorhanden sind. Daher wird dieser Modus auch Cursormodus genannt.

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

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

Der Kunde kann while direkt zur Bedienung verwenden.

  • Sie sind sicher neugierig, warum heißt unsere Iterator-Schnittstellenklasse nicht Iterator? Probieren Sie es aus und Sie werden wissen, dass PHP diese Schnittstelle für uns vorbereitet hat. Nach der Implementierung können Sie diese Klasse verwenden, die die Iterator-Schnittstelle implementiert. Schauen wir uns abschließend die Verwendung dieser Klasse an.
  • Haben Sie nicht zugestimmt, die Klassen zu durchlaufen? Warum ein Array hin und her übergeben? Studenten, die Java entwickelt haben, müssen wissen, dass in einer JavaBean-Klasse mit dem Namen „Object“ eine Variable vom Typ „List“, wie z. B. „List myList“, geschrieben wird, um die aktuelle Sammlung von Objekten darzustellen. Nachdem Sie dieser Liste während der Verwendung Daten hinzugefügt haben, können Sie Object.myList beim nächsten Mal direkt verwenden, um einen Datensatz abzurufen. Beispielsweise kann der von der Schnittstelle erhaltene JSON-Array-Inhalt in einem solchen Bean gespeichert werden. Zu diesem Zeitpunkt können wir einen Iterator verwenden, um nur das Array innerhalb unseres eigenen Objekts zu bearbeiten!
  • Der oben genannte Java-Inhalt wird vom Autor häufig bei der Android-Entwicklung verwendet. Manchmal verfügt die JavaBean der Datenbank auch über ein solches Array zum Speichern von Fremdschlüsseln. In PHP wird es jedoch im Allgemeinen selten verwendet, da sich die meisten AR-Objekte in PHP geringfügig vom Bean-Konzept in Java unterscheiden. Interessierte Studierende können mehr erfahren!

Unsere Mobiltelefonfabrik ist großartig. Wir haben selbst eine Produktionslinie aufgebaut. Wofür wird diese Produktionslinie hauptsächlich verwendet? Wir haben die Formmaschine an Fuji Kang übergeben und unsere Linie dient zum Lackieren von Mobiltelefonen. Wenn wir alle gelieferten Mobiltelefone (Aggregate) in verschiedene Produktionslinien (Iterator) stecken, helfen sie uns, die Farbe der aktuellen Produktionslinie nacheinander zu malen. Ist das nicht sehr leistungsstark? ! Bei der Technologie geht es nicht nur darum, Muscheln zu wechseln, wir können auch andere Dinge tun, wie zum Beispiel ein paar Lanyards oder so etwas hinzufügen. Wie auch immer, ich kann die Dinger anbringen es ist einfach zu bedienen? Einfach zu bedienen! !

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

实例

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

消息发送迭代器类图

Eine kurze Diskussion des Iteratormusters in 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视频教程

Das obige ist der detaillierte Inhalt vonEine kurze Diskussion des Iteratormusters in PHP. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen