Паттерн Итератор предоставляет механизм последовательного перебора элементов коллекции без раскрытия ее внутреннего представления.
Кроме того, перебор элементов выполняется объектом итератора, а не самой коллекцией.
Это упрощает интерфейс, и реализацию коллекции, а также способствует более логичному распределению обязанностей. При использовании итераторов коллекция избавляется от одной обязанности поддержки операций перебора данных.
Итератор предоставляет общий интерфейс перебора элементов коллекции, что позволяет применять полиморфизм в коде, использующем элементы коллекции.
Представим, что у нас есть два класса, реализующие две разных коллекции, суть проблемы состоит в том, чтобы клиент не знал как эти коллекции реализованы, но имел возможность обходить последовательно все коллекции.
Давайте представим ситуацию нас наняли в качестве разработчика для написания программного обеспечения автомата, который будет выводить информацию клиенту о меню, цене и блюдах.
Как мы знаем утром мы не едим мясо, супы итд, потому что это эти блюда употребляем в обед, а завтракаем более легкой пищей. Соответственно для этой ситуации у нас должно быть 2 коллекции, завтрак и обед. Но проблема еще заключается в том, что в автомате до нас реализовали коллекцию завтраков, и менять мы ее не можем. Для решения этих целей и был придуман паттерн Итератор. Мы реализуем интерфейс.
1 |
IEnumerator |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
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(); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
Меню ---- Завтрак Блиный гурман, 130 -- Блинчики со взбитыми яцами и тостом Обычны завтра из блинов, 130 -- Жареный блин с сосиской Блины с черникой, 230 -- Блины со свежей черникой Фруктовые блины, 230 -- Блины со свежей черникой и клубникой Обед Манная каша, 120 -- Манная каша на миндальном молоке с ванилью Чечевичный суп, 150 -- Чечевичный суп с томатами Суп рассольник, 180 -- Постный рассольник Фаршированные перцы, 230 -- Фаршированные перцы с грибами и кабачком Овощное рагу, 350 -- Овощное рагу с мясом Свинина, 550 -- Свинина под лимонной заправкой |