Паттерн Итератор предоставляет механизм последовательного перебора элементов коллекции без раскрытия ее внутреннего представления.
Кроме того, перебор элементов выполняется объектом итератора, а не самой коллекцией.
Это упрощает интерфейс, и реализацию коллекции, а также способствует более логичному распределению обязанностей. При использовании итераторов коллекция избавляется от одной обязанности поддержки операций перебора данных.
Итератор предоставляет общий интерфейс перебора элементов коллекции, что позволяет применять полиморфизм в коде, использующем элементы коллекции.
Представим, что у нас есть два класса, реализующие две разных коллекции, суть проблемы состоит в том, чтобы клиент не знал как эти коллекции реализованы, но имел возможность обходить последовательно все коллекции.
Давайте представим ситуацию нас наняли в качестве разработчика для написания программного обеспечения автомата, который будет выводить информацию клиенту о меню, цене и блюдах.
Как мы знаем утром мы не едим мясо, супы итд, потому что это эти блюда употребляем в обед, а завтракаем более легкой пищей. Соответственно для этой ситуации у нас должно быть 2 коллекции, завтрак и обед. Но проблема еще заключается в том, что в автомате до нас реализовали коллекцию завтраков, и менять мы ее не можем. Для решения этих целей и был придуман паттерн Итератор. Мы реализуем интерфейс.
IEnumerator
using System;
using System.Collections;
namespace Паттерн_Итератор
{
public class MenuItem
{
public string Name { get; }
public string Description { get; }
public bool Vegetarian { get; }
public double Price { get; }
public MenuItem(string name, string description, bool vegetarian, double price)
{
this.Name = name;
this.Description = description;
this.Vegetarian = vegetarian;
this.Price = price;
}
}
public class DinnerMenuIterator : IEnumerator
{
MenuItem []items;
int position = 0;
public DinnerMenuIterator(MenuItem[] items)
{
this.items = items;
}
public object Current
{
get
{
MenuItem menuItem = items[position];
position++;
return menuItem;
}
}
public bool MoveNext()
{
if (items == null || position >= items.Length)
{
return false;
}
else
{
return true;
}
}
public void Reset()
{
if (position <= 0)
{
throw new Exception("Вы не можете удалить товар пока не вызовите MoveNext() ");
}
if (items[position - 1] != null)
{
for (int i = 0; i < items.Length - 1; i++)
{
items[i] = items[i + 1];
}
items[items.Length - 1] = null;
}
}
}
public class BreakfastMenuIterator : IEnumerator
{
ArrayList items;
int position = 0;
public BreakfastMenuIterator(ArrayList items)
{
this.items = items;
}
public object Current
{
get
{
object menuItem = items[position];
position++;
return menuItem;
}
}
public bool MoveNext()
{
if (position >= items.Count || items[position] == null)
{
return false;
}
else
{
return true;
}
}
public void Reset()
{
if (position <= 0)
{
throw new Exception("Вы не можете удалить товар пока не вызовите MoveNext() ");
}
if (items[position - 1] != null)
{
for (int i = 0; i < items.Count-1; i++)
{
items[i] = items[i + 1];
}
items[items.Count - 1] = null;
}
}
}
public class DinnerMenu
{
MenuItem[] menuItems;
public DinnerMenu()
{
menuItems = new MenuItem[]
{
new MenuItem("Манная каша", "Манная каша на миндальном молоке с ванилью", true, 120),
new MenuItem("Чечевичный суп", "Чечевичный суп с томатами", true, 150),
new MenuItem("Суп рассольник", "Постный рассольник", true, 180),
new MenuItem("Фаршированные перцы", "Фаршированные перцы с грибами и кабачком", true, 230),
new MenuItem("Овощное рагу", "Овощное рагу с мясом", false, 350),
new MenuItem("Свинина", "Свинина под лимонной заправкой", false, 550),
};
}
//метод возвращает интерфейс IEnumerator, клиенту не нужно знать ничего о колекции.
//клиент просто переберает элементы
public IEnumerator CreateIterator()
{
return new DinnerMenuIterator(menuItems);
}
}
public class BreakfastMenu
{
ArrayList menuItems;
public BreakfastMenu()
{
menuItems = new ArrayList
{
new MenuItem("Блиный гурман", "Блинчики со взбитыми яцами и тостом", true, 130),
new MenuItem("Обычны завтра из блинов", "Жареный блин с сосиской", true, 130),
new MenuItem("Блины с черникой", "Блины со свежей черникой", true, 230),
new MenuItem("Фруктовые блины", "Блины со свежей черникой и клубникой", true, 230)
};
}
//метод возвращает интерфейс IEnumerator, клиенту не нужно знать ничего о колекции.
//клиент просто переберает элементы
public IEnumerator CreateIterator()
{
return new BreakfastMenuIterator(menuItems);
}
}
public class Automatic
{
BreakfastMenu breakfastMenu;
DinnerMenu dinnerMenu;
public Automatic(BreakfastMenu breakfastMenu, DinnerMenu dinnerMenu)
{
this.breakfastMenu = breakfastMenu;
this.dinnerMenu = dinnerMenu;
}
public void PrintMenu()
{
IEnumerator breakfastIterator = breakfastMenu.CreateIterator();
IEnumerator dinnerIterator = dinnerMenu.CreateIterator();
Console.WriteLine("Меню\n----\nЗавтрак");
PrintMenu(breakfastIterator);
Console.WriteLine("\nОбед");
PrintMenu(dinnerIterator);
}
void PrintMenu(IEnumerator iterator)
{
while (iterator.MoveNext())
{
MenuItem menuItem = (MenuItem)iterator.Current;
Console.WriteLine(menuItem.Name+", ");
Console.WriteLine(menuItem.Price+" -- ");
Console.WriteLine(menuItem.Description);
}
}
}
class Program
{
static void Main(string[] args)
{
BreakfastMenu breakfastMenu = new BreakfastMenu();
DinnerMenu dinnerfast = new DinnerMenu();
Automatic automatic = new Automatic(breakfastMenu, dinnerfast);
automatic.PrintMenu();
Console.ReadKey();
}
}
}
Меню
----
Завтрак
Блиный гурман,
130 --
Блинчики со взбитыми яцами и тостом
Обычны завтра из блинов,
130 --
Жареный блин с сосиской
Блины с черникой,
230 --
Блины со свежей черникой
Фруктовые блины,
230 --
Блины со свежей черникой и клубникой
Обед
Манная каша,
120 --
Манная каша на миндальном молоке с ванилью
Чечевичный суп,
150 --
Чечевичный суп с томатами
Суп рассольник,
180 --
Постный рассольник
Фаршированные перцы,
230 --
Фаршированные перцы с грибами и кабачком
Овощное рагу,
350 --
Овощное рагу с мясом
Свинина,
550 --
Свинина под лимонной заправкой
