Ітератор (англ. 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 ());
}
}