Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шаблоны и архитектура программ.doc
Скачиваний:
12
Добавлен:
04.05.2019
Размер:
558.08 Кб
Скачать

3.10. Шаблоны поведения: итератор, посредник, наблюдатель Итератор (Iterator)

Назначение шаблона Итератор – предоставить последовательный доступ к элементам коллекции без информации о её внутреннем устройстве. Дополнительно шаблон может реализовывать функционал по фильтрации элементов коллекции.

Концепция итераторов и перечислителей (также называемых генераторы) не является новой. Перечислители ответственны за предоставление следующего элемента коллекции, удовлетворяющего определенному критерию. В последние годы возможности создания итераторов и перечислителей были интегрированы в синтаксис многих языков программирования, что позволило упростить код и сделать реализацию шаблонов компактной. Диаграмма шаблона Итератор использует имена, применяемые в .NET Framework и языке C#.

Рис. 19. Шаблон Итератор.

При практической реализации шаблона Итератор на C#, безусловно, используются такие возможности, как перечислители, интерфейсы IEnumerable и IEnumerator, оператор yield. В качестве примера использования итераторов рассмотрим работу со структурой данных, соответствующей семейному дереву (рис. 20).

Рис. 20. Семейное дерево.

using System;

using System.Collections;

using System.Collections.Generic;

public class Tree<T> : IEnumerable<T>

{

public T Root { get; private set; }

public IList<Tree<T>> Leaves { get; private set; }

public Tree(T root, params Tree<T>[] leaves)

{

Root = root;

Leaves = Array.AsReadOnly(leaves);

}

public IEnumerable<T> Where(Func<T, bool> filter)

{

foreach (var p in this)

{

if (filter(p))

{

yield return p;

}

}

}

public IEnumerator<T> GetEnumerator()

{

yield return Root;

foreach (var leaf in Leaves)

{

foreach (var item in leaf)

{

yield return item;

}

}

}

IEnumerator IEnumerable.GetEnumerator()

{

return GetEnumerator();

}

}

public class Person

{

public string Name { get; set; }

public int Birth { get; set; }

public Person(string name, int birth)

{

Name = name;

Birth = birth;

}

public override string ToString()

{

return string.Format("[{0}, {1}]", Name, Birth);

}

}

public class TreeIteratorExample

{

private static void Main()

{

var family = new Tree<Person>(

new Person("Tom", 1950),

new Tree<Person>(new Person("Peter", 1976),

new Tree<Person>(new Person("James", 2000)),

new Tree<Person>(new Person("Sarah", 2002))

),

new Tree<Person>(new Person("Robert", 1978)),

new Tree<Person>(new Person("Mark", 1982)),

new Tree<Person>(new Person("Carrie", 2005))

);

foreach (var person in family.Where(p => p.Birth > 1980))

{

Console.WriteLine(person);

}

}

}