Назначение
Iterator предоставляет унифицированный способ последовательного доступа к элементам коллекций разных структур.
Описание
Требуется получить доступ последовательно к всем элементам агрегатной структуры
данных (коллекции). Для итерации по коллекции используется объект типа Iterator
.
Этот объект позволяет:
- проверить, достигнут ли конец коллекции
- получить текущий элемент коллекции
- сдвинуть указатель текущего элемента на следующий
Чтобы получить Iterator
необходимо обратиться к коллекции, которая
должна предоставлять для этого интерфейс Iterable
. Интерфейс Iterable
является интерфейсом фабрики
которая производит продукт Iterator
.
Конкретная коллекция и соответствующей ей конкретный итератор всегда взаимосвязаны между собой. Коллекция создает итератор, а итератор должен иметь ссылку на коллекцию чтобы по ней итерироваться.
Iterator позволяет не выявлять все элементы сразу, а генерировать их динамически и даже создавать бесконечные коллекции. Кроме того с помощью итератора можно запомнить место в котором приостановлена итерация и возобновить её при необходимости.
Реализация
Iterator
для последовательного доступа к коллекцииПримеры
Все коллекции jdk Collection<E>
реализуют интерфейс Iterable<E>
. Но преимущество
шаблона в том, что реализовать этот интерфейс можно самостоятельно для новой структуры
данных.
Варианты
- интерфейс
Iterator
может быть более широким, предоставлять методы для перехода к предыдущим элементам или перемещения по другим направлениям Iterator
может быть внутренним классом или внешним. Внутренний не статический имеет доступ к структуре данных и связь замыкающем объектом, но инкапсулирует позицию, указывающую на элемент данных, поэтому может создано несколько экземпляровItertor
. ВнешнийIterator
при создании может получать ссылку на коллекцию через конструкторpublic Iterator<E> iterator() { return new ConcreteIterator<E>(this); }
Iterator
может быть копирующем состояние объекта при его создании, или защищенным через счетчикmodCount
- если число изменений не соответствует ожидаемому, возбуждается исключение- интерфейс
Iterator
может быть выражен 3, 2, 1 методом. Согласно принципу Command–query separation (CQS), следует разделять методы, которые выполняют команды (изменяют состояние или данные, command, “update”) и методы, которые выполняют запросы (query, “select”). Руководствуясь этим принципом правильнее было бы сделать 3 метода:boolean hasNext()
- queryvoid next()
- commandE current()
- query
Но можно некоторые методы объединить в один, как например в Java
boolean hasNext()
,E next()
. Даже можно сделать через единственный метод, который возвращает специальное значение, показывающее, что элементов больше нет или возбуждает исключение.
Чем отличается
Factory Method Iterator является
примером реализации Factory Method. Интерфейс Iterable
является интерфейсом
фабрики, а продукт фабрики – сами итераторы Iterator
.
Adapter Iterator является адаптером, который адаптирует коллекцию к интерфейсу последовательного перебора.
Ссылки
https://java-design-patterns.com/patterns/iterator/
https://github.com/iluwatar/java-design-patterns/tree/master/iterator
https://refactoring.guru/design-patterns/iterator