В объектно-ориентированном программировании шаблон итератора — это шаблон проектирования , в котором итератор используется для обхода контейнера и доступа к его элементам. Шаблон итератора отделяет алгоритмы от контейнеров; в некоторых случаях алгоритмы обязательно зависят от контейнера и, таким образом, не могут быть отделены.
Например, гипотетический алгоритм SearchForElement может быть реализован в общем виде с использованием указанного типа итератора, а не как алгоритм, специфичный для контейнера. Это позволяет использовать SearchForElement в любом контейнере, который поддерживает требуемый тип итератора.
Шаблон проектирования «Итератор » [1] — один из 23 известных шаблонов проектирования «Банды четырех» , которые описывают, как решать повторяющиеся проблемы проектирования для разработки гибкого и повторно используемого объектно-ориентированного программного обеспечения, то есть объектов, которые проще реализовывать, изменять, тестировать и повторно использовать.
[2]
Определение операций доступа и обхода в интерфейсе агрегата негибко, поскольку оно привязывает агрегат к определенным операциям доступа и обхода и делает невозможным добавление новых операций позже без необходимости изменения интерфейса агрегата.
Различные итераторы могут использоваться для доступа и обхода агрегата различными способами.
Новые операции доступа и обхода могут быть определены независимо путем определения новых итераторов.
См. также класс UML и диаграмму последовательности ниже.
Суть шаблона «Итератор» заключается в «предоставлении способа последовательного доступа к элементам совокупного объекта без раскрытия его базового представления». [3]
В приведенной выше диаграмме классов UML класс ссылается (1) на интерфейс для создания объекта ( ) и (2) на интерфейс для обхода объекта ( ). Класс реализует интерфейс путем доступа к классу.Client
Aggregate
Iterator
createIterator()
Iterator
Aggregate
next(),hasNext()
Iterator1
Iterator
Aggregate1
Диаграмма последовательности UML
показывает взаимодействия во время выполнения: объект вызывает объект , который создает объект и возвращает его в . Затем он использует для обхода элементов объекта .Client
createIterator()
Aggregate1
Iterator1
Client
Client
Iterator1
Aggregate1
Некоторые языки стандартизируют синтаксис. Яркими примерами являются C++ и Python.
C++ реализует итераторы с семантикой указателей в этом языке. В C++ класс может перегружать все операции указателей, поэтому можно реализовать итератор, который действует более или менее как указатель, с разыменованием, инкрементом и декрементом. Это имеет то преимущество, что алгоритмы C++, такие как, std::sort
могут быть немедленно применены к обычным старым буферам памяти, и что нет нового синтаксиса для изучения. Однако для этого требуется итератор «end» для проверки на равенство, а не позволяет итератору знать, что он достиг конца. В языке C++ мы говорим, что итератор моделирует концепцию итератора .
Эта реализация C++11 основана на главе «Обобщение вектора еще раз». [5]
#include <iostream> #include <stdexcept> #include <initializer_list> class Vector { public : using iterator = double * ; iterator begin () { return elem ; } iterator end () { return elem + sz ; } Vector ( std :: initializer_list <double> lst ) : elem ( nullptr ), sz ( 0 ) { sz = lst.size ( ); elem = new double [ sz ] ; double * p = elem ; for ( auto i = lst.begin (); i ! = lst.end ( ) ; ++ i , ++ p ) { * p = * i ; } } ~ Vector ( ) { delete [ ] elem ; } int size ( ) const { return sz ; } double & Operator []( int n ) { if ( n < 0 || n >= sz ) throw std :: out_of_range ( "Vector::operator[]" ); return elem [ n ]; } Vector ( const Vector & ) = delete ; // правило трех Vector & Operator = ( const Vector & ) = delete ; private : double * elem ; int sz ; }; int main () { Вектор v = { 1.1 * 1.1 , 2.2 * 2.2 }; для ( const auto & x : v ) { std :: cout << x << '\n' ; } для ( auto i = v . begin (); i != v . end (); ++ i ) { std :: cout << * i << '\n' ; } для ( auto i = 0 ; i <= v . size (); ++ i ) { std :: cout << v [ i ] << '\n' ; } }
Вывод программы:
1.21 4.84 1.21 4.84 1.21 4.84 terminate вызывается после выдачи экземпляра ' std :: out_of_range ' what ( ) : Vector :: Operator [ ]