Шаблон проектирования итератора — это широко используемый шаблон, обеспечивающий очень полезную абстракцию. Шаблон итератора используется для доступа и обхода элементов коллекции без необходимости понимания или раскрытия базовой структуры коллекции.
Итератор — это поведенческий шаблон проектирования, в котором вы используете итератор для последовательного перечисления элементов контейнера, то есть коллекции. Поведенческие шаблоны проектирования — это те, которые управляют совместной работой объектов и делегированием ответственности между объектами.
Одним из преимуществ шаблона итератора является то, что он позволяет изменять реализацию коллекции, не изменяя способ доступа к коллекции извне.
В этой статье мы рассмотрим простую реализацию шаблона проектирования итератора с использованием C#. Участниками типичной реализации шаблона итератора являются:
Iterator
. Обычно это интерфейс (или абстрактный класс), который определяет интерфейс для обхода элементов контейнера.ConcreteIterator
. Это класс, реализующий интерфейсIterator
.Aggregate
. Обычно это абстрактная коллекция, определяющая интерфейс для создания экземпляра итератора.ConcreteAggregate
. Это класс, который реализуетAggregate
и возвращает экземпляр конкретного итератора.
Создать коллекцию
Давайте начнем. Сначала создайте проект консольного приложения в Visual Studio. Затем создайте следующий класс с именем Author
.
public class Author { private string firstName, lastName; public Author(string firstName, string lastName) { this.firstName = firstName; this.lastName = lastName; } public string Name { get { return this.firstName + “\t”+ this.lastName; } } }
Обратите внимание, что класс Author
представляет коллекцию, которую мы хотим сохранить внутри контейнера, а затем выполнить итерацию. Класс Author
содержит конструктор параметров, который принимает два аргумента, то есть имя и фамилию автора. Свойство Name
класса Author
возвращает полное имя автора.
Создайте интерфейс абстрактного контейнера
Вот интерфейс абстрактного контейнера с именем IAbstractContainer
. Этот интерфейс содержит объявление метода CreateIterator()
.
public interface IAbstractContainer { Iterator CreateIterator(); }
Реализовать контейнер
Класс Container
расширяет интерфейс IAbstractContainer
и реализует метод CreateIterator()
. Он также содержит свойство Count
, которое возвращает количество элементов в коллекции Author
. Также есть индексатор. Мы будем использовать индексатор для извлечения данных из коллекции позже.
public class Container : IAbstractContainer { private List<Author> authors = new List<Author>(); public Iterator CreateIterator() { return new Iterator(this); } public int Count { get { return authors.Count; } } public Author this[int index] { get { return authors[index]; } set { authors.Add(value); } } }
Создайте абстрактный итератор
Следующим в нашем списке типов для реализации является абстрактный итератор. Интерфейс IAbstractIterator
содержит объявление операций, которые будет реализовывать конкретный класс итератора.
public interface IAbstractIterator { Author FirstItem(); Author NextItem(); bool IsDone { get; } }
Реализовать итератор
Класс Iterator
расширяет интерфейс IAbstractIterator
. Iterator
используется для инкапсуляции реализации итерации коллекции. Обратите внимание, как он использует индекс для отслеживания процесса итерации.
public class Iterator : IAbstractIterator { private Container aggregate; private int currentIndex = 0; private int increment = 1; public Iterator(Container container) { aggregate = container; } public Author FirstItem() { currentIndex = 0; return aggregate[currentIndex]; } public Author NextItem() { currentIndex += increment; if (!IsDone) return aggregate[currentIndex] as Author; return null; } public bool IsDone { get { if (currentIndex >= aggregate.Count) return true; return false; } } }
Итерация по элементам коллекции
Наконец, мы создадим экземпляр контейнера, сохраним объекты в контейнере, а затем пройдемся по элементам коллекции. В приведенном ниже фрагменте кода обратите внимание, как мы создаем пять экземпляров класса Author
, присваиваем значения свойствам firstName
и lastName
, а затем создаем экземпляр Iterator
, вызывая метод CreateIterator()
для экземпляра контейнера.
static void Main(string[] args) { Container container = new Container(); container[0] = new Author(“Joydip”, “Kanjilal”); container[1] = new Author(“Michael”, “Stevens”); container[2] = new Author(“Steve”, “Jones”); container[3] = new Author(“Steve”, “Smith”); container[4] = new Author(“Jack”, “Gibbs”); Iterator iterator = container.CreateIterator(); for (Author item = iterator.FirstItem(); !iterator.IsDone; item = iterator.NextItem()) { Console.WriteLine(item.Name); } Console.ReadKey(); }