Эта статья является частью нашего курса Академии под названием « Шаблоны проектирования Java» .
В этом курсе вы изучите огромное количество шаблонов проектирования и увидите, как они реализуются и используются в Java. Вы поймете причины, почему шаблоны так важны, и узнаете, когда и как применять каждый из них. Проверьте это здесь !
Содержание
1. Введение
Агрегированный объект, такой как список, должен предоставить вам доступ к его элементам, не раскрывая его внутреннюю структуру. Более того, вы можете просмотреть список различными способами, в зависимости от того, чего вы хотите достичь. Но вы, вероятно, не хотите разбрасывать интерфейс List
операциями для различных обходов, даже если вы можете предвидеть те, которые вам понадобятся. Вам также может потребоваться, чтобы в одном списке было несколько ожидающих обходов.
Шаблон Iterator позволяет вам делать все это. Основная идея в этом шаблоне состоит в том, чтобы взять на себя ответственность за доступ и обход из объекта списка и поместить его в объект итератора. Класс Iterator
определяет интерфейс для доступа к элементам списка. Объект итератора отвечает за отслеживание текущего элемента; то есть он знает, какие элементы уже пройдены.
2. Что такое шаблон итератора
Цель шаблона проектирования итератора — предоставить способ последовательного доступа к элементам агрегатного объекта без раскрытия его базового представления.
Шаблон Iterator позволяет клиентскому объекту обращаться к содержимому контейнера последовательно, не имея никаких знаний о внутреннем представлении его содержимого. Термин «контейнер», использованный выше, может быть просто определен как набор данных или объектов. Объекты в контейнере, в свою очередь, могут быть коллекциями, что делает его коллекцией коллекций.
Шаблон Iterator позволяет клиентскому объекту проходить через эту коллекцию объектов (или контейнер), не имея контейнера, чтобы показать, как данные хранятся внутри. Для этого шаблон итератора предполагает, что объект-контейнер должен быть спроектирован так, чтобы предоставлять открытый интерфейс в форме объекта итератора для различных клиентских объектов для доступа к его содержимому. Объект Iterator содержит открытые методы, позволяющие клиентскому объекту перемещаться по списку объектов в контейнере.
Итератор
- Определяет интерфейс для доступа и обхода элементов.
ConcreteIterator
- Реализует интерфейс Iterator.
- Отслеживает текущую позицию в обходе агрегата.
заполнитель
- Определяет интерфейс для создания объекта Iterator.
ConcreteAggregate
- Реализует интерфейс создания Iterator для возврата экземпляра правильного ConcreteIterator.
3. Реализация шаблона проектирования итератора
Давайте реализуем шаблон проектирования Iterator, используя класс Shape
. Мы будем хранить и повторять объекты Shape
используя итератор.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
package com.javacodegeeks.patterns.iteratorpattern; public class Shape { private int id; private String name; public Shape( int id, String name){ this .id = id; this .name = name; } public int getId() { return id; } public void setId( int id) { this .id = id; } public String getName() { return name; } public void setName(String name) { this .name = name; } @Override public String toString(){ return "ID: " +id+ " Shape: " +name; } } |
Простой класс Shape
имеет id
и name
качестве своих атрибутов.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
package com.javacodegeeks.patterns.iteratorpattern; public class ShapeStorage { private Shape []shapes = new Shape[ 5 ]; private int index; public void addShape(String name){ int i = index++; shapes[i] = new Shape(i,name); } public Shape[] getShapes(){ return shapes; } } |
Приведенный выше класс используется для хранения объектов Shape
. Класс содержит массив типа Shape
, для простоты мы инициализировали этот массив до 5. Метод addShape
используется для добавления объекта Shape
в массив и увеличения индекса на единицу. Метод getShapes
возвращает массив типа Shape
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
package com.javacodegeeks.patterns.iteratorpattern; import java.util.Iterator; public class ShapeIterator implements Iterator<Shape>{ private Shape [] shapes; int pos; public ShapeIterator(Shape []shapes){ this .shapes = shapes; } @Override public boolean hasNext() { if (pos >= shapes.length || shapes[pos] == null ) return false ; return true ; } @Override public Shape next() { return shapes[pos++]; } @Override public void remove() { if (pos <= 0 ) throw new IllegalStateException( "Illegal position" ); if (shapes[pos- 1 ] != null ){ for ( int i= pos- 1 ; i<(shapes.length- 1 );i++){ shapes[i] = shapes[i+ 1 ]; } shapes[shapes.length- 1 ] = null ; } } } |
Приведенный выше класс является Iterator
класса Shape
. Класс реализует интерфейс Iterator
и определяет все методы интерфейса Iterator
.
Метод hasNext
возвращает boolean
если остался элемент. Метод next возвращает следующий элемент из коллекции, а метод remove удаляет текущий элемент из коллекции.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package com.javacodegeeks.patterns.iteratorpattern; public class TestIteratorPattern { public static void main(String[] args) { ShapeStorage storage = new ShapeStorage(); storage.addShape( "Polygon" ); storage.addShape( "Hexagon" ); storage.addShape( "Circle" ); storage.addShape( "Rectangle" ); storage.addShape( "Square" ); ShapeIterator iterator = new ShapeIterator(storage.getShapes()); while (iterator.hasNext()){ System.out.println(iterator.next()); } System.out.println( "Apply removing while iterating..." ); iterator = new ShapeIterator(storage.getShapes()); while (iterator.hasNext()){ System.out.println(iterator.next()); iterator.remove(); } } } |
Приведенный выше код приведет к следующему выводу:
1
2
3
4
5
6
7
8
9
|
ID: 0 Shape: Polygon ID: 1 Shape: Hexagon ID: 2 Shape: Circle ID: 3 Shape: Rectangle ID: 4 Shape: Square Apply removing while iterating... ID: 0 Shape: Polygon ID: 2 Shape: Circle ID: 4 Shape: Square |
В приведенном выше классе мы создали объект ShapeStorage
и сохранили в нем объекты Shape
. Затем мы создали объект ShapeIterator
и присвоили ему формы. Мы повторили дважды, сначала без вызова метода remove, а затем с методом remove.
Выходные данные показывают влияние метода удаления. На первой итерации итератор печатает все фигуры, но когда вызывается метод remove, он сначала печатает текущую фигуру и перемещается к следующей фигуре. Затем мы вызвали метод remove, который удаляет текущую фигуру, а затем итератор указывает на следующий доступный объект формы.
Поэтому в выводе после «Применить удаление во время итерации…» отображаются только объекты 0, 2 и 4 фигур.
4. Внутренние и внешние итераторы
Итератор может быть выполнен как внутренний итератор или как внешний итератор.
4.1 Внутренние итераторы
- Сама коллекция предлагает методы, позволяющие клиенту посещать различные объекты в коллекции. Например, класс
java.util.ResultSet
содержит данные, а также предлагает такие методы, как next для навигации по списку элементов. - В любой момент времени в коллекции может быть только один итератор.
- Коллекция должна поддерживать или сохранять состояние итерации.
4.2 Внешние итераторы
- Функциональность итерации отделена от коллекции и находится внутри другого объекта, называемого итератором. Обычно сама коллекция возвращает соответствующий объект итератора клиенту в зависимости от входных данных клиента. Например, класс
java.util.Vector
имеет свой итератор, определенный в виде отдельного объекта типаEnumeration
. Этот объект возвращается клиентскому объекту в ответ на вызов методаelements()
. - В любой момент времени в данной коллекции может быть несколько итераторов.
- Затраты на хранение состояния итерации не связаны с коллекцией. Он принадлежит эксклюзивному объекту Iterator.
5. Когда использовать шаблон проектирования итератора
Используйте шаблон Iterator:
- Для доступа к содержимому совокупного объекта, не раскрывая его внутреннего представления.
- Для поддержки множественных обходов агрегатных объектов.
- Обеспечить единый интерфейс для обхода различных агрегатных структур (то есть для поддержки полиморфной итерации).
6. Шаблон итератора в JDK
-
java.util.Iterator
-
java.util.Enumeration
7. Загрузите исходный код
Это был урок по шаблону дизайна итераторов. Вы можете скачать исходный код здесь: IteratorPattern-Project