Шаблон Iterator

Шаблон проектирования Итератор — один из поведенческих паттернов, который позволяет последовательно обходить элементы коллекций различных типов без раскрытия внутренней структуры самой коллекции. Это особенно полезно, когда разные классы предоставляют доступ к своим данным разными способами, но нам важно получать единообразное представление об элементах независимо от типа контейнера.

Когда применяется?

  • Необходимо обеспечить последовательный доступ ко всем элементам сложной структуры данных.
  • Нужно скрыть внутреннюю реализацию структуры данных от клиентов, предоставляя возможность перебора элементов прозрачно и легко.
  • Требуется поддержка нескольких вариантов итерации одной и той же структуры одновременно.

Как устроено?

Основные компоненты шаблона:

  • Агрегат: класс, представляющий коллекцию объектов. Агрегат реализует метод createIterator(), возвращающий объект класса Итератора, соответствующего данному типу агрегата.
  • Итератор: интерфейс или абстрактный базовый класс, определяющий методы перемещения между элементами (next()), проверки достижения конца последовательности (hasNext()) и возвращения текущего элемента (current()).
  • Конкретный Итератор: реализация интерфейса Итератора для конкретного агрегата. Конкретный итератор хранит внутреннее состояние позиции в агрегации и управляет перемещением по нему.

Пример реализации на PHP:

// Интерфейс Итераторов
interface Iterator {
    public function next();
    public function hasNext(): bool;
}

// Абстрактная коллекция (агрегат)
abstract class Aggregate {
    abstract public function createIterator(): Iterator;
}

// Реализация конкретной коллекции
class ConcreteAggregate extends Aggregate {
    private array $items = [];
    
    // Метод создает соответствующий итератор
    public function createIterator(): Iterator {
        return new ConcreteIterator($this);
    }
    
    // Методы добавления/получения элементов коллекции
    public function addItem(string $item): void {
        $this->items[] = $item;
    }
    
    public function getItems(): array {
        return $this->items;
    }
}

// Конкретный итератор
class ConcreteIterator implements Iterator {
    private int $position = 0;
    private ConcreteAggregate $aggregate;
    
    public function __construct(ConcreteAggregate $aggregate) {
        $this->aggregate = $aggregate;
    }
    
    public function next() {
        if ($this->hasNext()) {
            return $this->aggregate->getItems()[$this->position++];
        }
        return null;
    }
    
    public function hasNext(): bool {
        return isset($this->aggregate->getItems()[$this->position]);
    }
}

// Пример использования
$collection = new ConcreteAggregate();
$collection->addItem('Элемент 1');
$collection->addItem('Элемент 2');
$collection->addItem('Элемент 3');

$iterator = $collection->createIterator();
while ($iterator->hasNext()) {
    echo $iterator->next() . "\n";
}

Преимущества

  • Упрощение клиента: клиенту достаточно вызывать стандартные методы итератора, не заботясь о внутреннем устройстве коллекции.
  • Возможность поддерживать различные способы обхода одних и тех же структур данных.
  • Сокрытие деталей внутреннего устройства агрегатов.

Таким образом, шаблон Итератор помогает абстрагироваться от конкретных реализаций контейнеров и обеспечивает единый способ обработки элементов разных коллекций.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *