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