Итератор (англ. Iterator ) относится к классу шаблонов поведения. Используется в составных объектах.
Предоставляет доступ к своим внутренним полям, не раскрывая их структуру.
Зачастую этот шаблон используется вместо массива объектов, чтобы не только предоставить доступ к элементам,
но и наделить некоторой логикой. Это может быть ограничение доступа, сортировка или любая другая операция
над множеством объектов.
Из коробки PHP, нам доступен интерфейс Iterator
.
Метод Iterator->current()
возвращает текущий элемент
Метод Iterator->next()
перемещает указатель на следующий элемент
Метод Iterator->key()
возвращает индекс текущего элемента
Метод Iterator->valid()
проверяет, существует ли текущий элемент или нет
Метод Iterator->rewind()
переводит указатель текущего элемента на первый
Worker.php
<?php
namespace DesignPatterns\Behavioral\Iterator ;
/**
* Class Worker
* @package DesignPatterns\Behavioral\Iterator
*/
class Worker
{
/**
* @var string
*/
protected $name ;
/**
* Worker constructor.
*
* @param string $name
*/
public function __construct ( string $name )
{
$this -> name = $name ;
}
/**
* @return string
*/
public function getName (): string
{
return $this -> name ;
}
}
WorkersList.php
<?php
namespace DesignPatterns\Behavioral\Iterator ;
use Countable ;
use Iterator ;
/**
* Class WorkersList
* @package DesignPatterns\Behavioral\Iterator
*/
class WorkersList implements Iterator , Countable
{
/**
* @var Worker[]
*/
protected $workers = [];
/**
* @var int
*/
protected $currentIndex = 0 ;
/**
* @param Worker $worker
*/
public function addWorker ( Worker $worker )
{
$this -> workers [] = $worker ;
}
/**
* @return Worker
*/
public function current (): Worker
{
return $this -> workers [ $this -> currentIndex ];
}
/**
* @return void
*/
public function next ()
{
$this -> currentIndex ++ ;
}
/**
* @return int
*/
public function key (): int
{
return $this -> currentIndex ;
}
/**
* @return bool
*/
public function valid (): bool
{
return isset ( $this -> workers [ $this -> currentIndex ]);
}
/**
* @return void
*/
public function rewind ()
{
$this -> currentIndex = 0 ;
}
/**
* @return int
*/
public function count (): int
{
return count ( $this -> workers );
}
}
Test case:
IteratorTest.php
<?php
namespace DesignPatterns\Tests\Behavioral\Iterator ;
use DesignPatterns\Behavioral\Iterator\Worker ;
use DesignPatterns\Behavioral\Iterator\WorkersList ;
class IteratorTest extends \ PHPUnit_Framework_TestCase
{
public function testWorkerGetName ()
{
$name = 'TestName' ;
$worker = new Worker ( $name );
$this -> assertEquals ( $name , $worker -> getName ());
}
public function testCountList ()
{
$ivanWorker = new Worker ( 'Ivan' );
$petrWorker = new Worker ( 'Petr' );
$andreyWorker = new Worker ( 'Andrey' );
$workersList = new WorkersList ();
$workersList -> addWorker ( $ivanWorker );
$workersList -> addWorker ( $petrWorker );
$workersList -> addWorker ( $andreyWorker );
$this -> assertCount ( 3 , $workersList );
}
public function testWorkersListKey ()
{
$workersList = new WorkersList ();
$this -> assertEquals ( 0 , $workersList -> key ());
$workersList -> next ();
$this -> assertEquals ( 1 , $workersList -> key ());
$workersList -> next ();
$this -> assertEquals ( 2 , $workersList -> key ());
}
public function testWorkersListValid ()
{
$ivanWorker = new Worker ( 'Ivan' );
$petrWorker = new Worker ( 'Petr' );
$andreyWorker = new Worker ( 'Andrey' );
$workersList = new WorkersList ();
$workersList -> addWorker ( $ivanWorker );
$workersList -> addWorker ( $petrWorker );
$workersList -> addWorker ( $andreyWorker );
$this -> assertEquals ( true , $workersList -> valid ());
$workersList -> next ();
$this -> assertEquals ( true , $workersList -> valid ());
$workersList -> next ();
$this -> assertEquals ( true , $workersList -> valid ());
$workersList -> next ();
$this -> assertEquals ( false , $workersList -> valid ());
}
public function testWorkersListResetKey ()
{
$workersList = new WorkersList ();
$this -> assertEquals ( 0 , $workersList -> key ());
$workersList -> next ();
$this -> assertEquals ( 1 , $workersList -> key ());
$workersList -> next ();
$this -> assertEquals ( 2 , $workersList -> key ());
$workersList -> rewind ();
$this -> assertEquals ( 0 , $workersList -> key ());
}
public function testWorkerListCurrentWorker ()
{
$ivanWorker = new Worker ( 'Ivan' );
$petrWorker = new Worker ( 'Petr' );
$andreyWorker = new Worker ( 'Andrey' );
$workersList = new WorkersList ();
$workersList -> addWorker ( $ivanWorker );
$workersList -> addWorker ( $petrWorker );
$workersList -> addWorker ( $andreyWorker );
$this -> assertSame ( $ivanWorker , $workersList -> current ());
$workersList -> next ();
$this -> assertSame ( $petrWorker , $workersList -> current ());
$workersList -> next ();
$this -> assertSame ( $andreyWorker , $workersList -> current ());
$workersList -> rewind ();
$this -> assertSame ( $ivanWorker , $workersList -> current ());
}
}