
- •А.А. Волосевич
- •3. Шаблоны и архитектура программ
- •3.1. Модульное тестирование
- •3.2. Шаблоны проектирования
- •3.3. Структурные шаблоны: Декоратор, Заместитель, мост Декоратор (Decorator)
- •Заместитель (Proxy)
- •Мост (Bridge)
- •3.4. Структурные шаблоны: компоновщик и приспособленец Компоновщик (Composite)
- •Приспособленец (Flyweight)
- •3.5. Структурные шаблоны: адаптер и фасад Адаптер (Adapter)
- •Фасад (Façade)
- •3.6. Порождающие шаблоны: прототип, фабричный метод, одиночка Прототип (Prototype)
- •Фабричный метод (Factory method)
- •Одиночка (Singleton)
- •3.7. Порождающие шаблоны: абстрактная фабрика и строитель Абстрактная фабрика (Abstract factory)
- •Строитель (Builder)
- •3.8. Шаблоны поведения: стратегия, состояние, шаблонный метод Стратегия (Strategy)
- •Состояние (State)
- •Шаблонный метод (Template method)
- •3.9. Шаблоны поведения: цепочка обязанностей и команда Цепочка обязанностей (Chain of responsibility)
- •Команда (Command)
- •3.10. Шаблоны поведения: итератор, посредник, наблюдатель Итератор (Iterator)
- •Посредник (Mediator)
- •Наблюдатель (Observer)
- •3.11. Шаблоны поведения: посетитель, интерпретатор, хранитель Посетитель (Visitor)
- •Интерпретатор (Interpreter)
- •Хранитель (Memento)
- •3.12. Некоторые неклассические шаблоны проектирования
- •Неизменный объект (Immutable object)
- •Пул объектов (Object pool)
- •Отложенная инициализация (Lazy initialization)
- •Нулевой объект (Null object)
- •3.13. Антипаттерны
- •3.14. Архитектура прогРаммного Обеспечения
- •«Клиент-сервер»
- •Архитектура, основанная на использовании компонентов
- •Многоуровневая архитектура
- •Шина сообщений
- •Выделенное представление
- •Объектно-ориентированная архитектура
- •Архитектура, ориентированная на сервисы
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);
}
}
}