|
16. Ітератор — Iterator
ADO в Delphi AJAX Android C++ CakePHP CMS COM CSS Delphi Flash Flex HTML Internet Java JavaScript MySQL PHP RIA SCORM Silverlight SQL UML XML Бази даних Веб-розробка Генетичні алгоритми ГІС Гітара Дизайн Економіка Інтелектуальні СДН Колір Масаж Математика Медицина Музика Нечітка логіка ООП Патерни Подання знань Розкрутка сайту, SEO САПР Сесії в PHP Системне програмування Системний аналіз Тестологія Тестування ПЗ Фреймворки Штучний інтелект
|
16. Ітератор — Iterator
Уявіть, що ви розробник статегічної воєнної гри. Армія має складну структуру: вона складається із героя і трьох груп. Коли генерал видає указ і ресурси щоб полікувати всіх воїнів (герой також є воїном), ви хочете проітерувати по всіх солдатах і викликати метод Treat() на кожному екземплярі. Як це можна зробити легко і без вникання в структуру армії? Ітератор дозволяє доступатися почергово до елементів будь-якої колекції без вникання в суть її імплементації. Таким чином в застосуванні до нашої проблеми, ми хочемо щоб SoldiersIterator «пробігся» по всіх солдатах. Код нище показує використання Ітератора. Уривок коду 16.1. Використання патерну — ітерування по арміїvar iterator = new SoldiersIterator(earthArmy); while (iterator.HasNext()) { var currSoldier = iterator.Next(); currSoldier.Treat(); }
Як бачимо, ми отримали екземпляр класу ітератора SoldiersIterator. І простим циклом проходимося по всіх солдатах армії. Це дуже легко, що і є основним завданням ітератора. Уривок коду 16.2. Структура армії
var andriybuday = new Hero("Andriy Buday");
var earthArmy = new Army(andriybuday);
var groupA = new Group();
for (int i = 1; i < 4; ++i) groupA.AddNewSoldier(new Soldier("Alpha:" + i));
var groupB = new Group();
for (int i = 1; i < 3; ++i) groupB.AddNewSoldier(new Soldier("Beta:" + i));
var groupC = new Group();
for (int i = 1; i < 2; ++i) groupC.AddNewSoldier(new Soldier("Gamma:" + i));
earthArmy.AddArmyGroup(groupB);
earthArmy.AddArmyGroup(groupA);
earthArmy.AddArmyGroup(groupC);
Герой (Hero) — це клас унаслідуваний від солдата (Soldier) і основна різниця полягає в тому, що він має вищий початковий рівень здоров’я. Уривок коду 16.3. Солдат та солдат-герой
class Soldier
{
public String Name;
public int Health;
private const int SoldierHealthPoints = 100;
protected virtual int MaxHealthPoints { get { return SoldierHealthPoints; } }
public Soldier(String name)
{
Name = name;
}
public void Treat()
{
Health = MaxHealthPoints;
Console.WriteLine(Name);
}
}
class Hero : Soldier
{
private const int HeroHealthPoints = 500;
protected override int MaxHealthPoints { get { return HeroHealthPoints; } }
public Hero(String name)
: base(name)
{
}
}
То ж, якщо ми можемо рухатися по складній колекції так легко, де ж вся складність? Звісно, вона інкапсульована в конкретному класі ітератора. Уривок коду 16.4. Ітератор і складна логіка ітерування (яку не раджу читати)
class SoldiersIterator
{
private readonly Army _army;
private bool _heroIsIterated;
private int _currentGroup;
private int _currentGroupSoldier;
public SoldiersIterator(Army army)
{
_army = army;
_heroIsIterated = false;
_currentGroup = 0;
_currentGroupSoldier = 0;
}
public bool HasNext()
{
if (!_heroIsIterated) return true;
if (_currentGroup < _army.ArmyGroups.Count) return true;
if (_currentGroup == _army.ArmyGroups.Count - 1)
if (_currentGroupSoldier < _army.ArmyGroups[_currentGroup].Soldiers.Count)
return true;
return false;
}
public Soldier Next()
{
Soldier nextSoldier;
if (_currentGroup < _army.ArmyGroups.Count)
{
// В кожній групі ітеруємо по кожному солдату
if (_currentGroupSoldier < _army.ArmyGroups[_currentGroup].Soldiers.Count)
{
nextSoldier =
_army.ArmyGroups[_currentGroup].Soldiers[_currentGroupSoldier];
_currentGroupSoldier++;
}
else
{
_currentGroup++;
_currentGroupSoldier = 0;
return Next();
}
}
// Герой останнім покидає поле бою
else if (!_heroIsIterated)
{
_heroIsIterated = true;
return _army.ArmyHero;
}
else
{
// Викидуємо виняток
throw new Exception("End of colletion");
}
return nextSoldier;
}
}
Цей приклад дещо відхиляється від стандартного. Я собі поставив за мету підкреслити головне завдання, яке вирішує паттерн. Головною різницею між моїм поясненням і тоннами інших пояснень є те, що стандартні є більш абстраговані. Я створював потрібний нам ітератор таким чином: Уривок коду 16.5. Просте створення ітератораvar iterator = new SoldiersIterator(earthArmy); Але зазвичай створення ітератора також інкапсулюється під методом агрегата. Це потрібно в тих ситуаціях, коли ми хочемо мати декілька різних ітераторів (скажімо, ще один тільки для героїв). Мій код міг би виглядати так: Уривок коду 16.6. Класичне створення ітератораAbstractIterator iterator = AbstractArmy.GetSoldiersIterator(); Уривок коду 16.7. В .NET є готові інтерфейси IEnumerable та IEnumerator, що нам допомагають
var list = new List<int>();
// GetEnumerator це метод інтерфейсу IEnumerable (агрегат)
var enumerator = list.GetEnumerator();
// MoveNext метод інтерфейсу IEnumerator і буде методом ітератора
enumerator.MoveNext();
По матеріалам книги Андрія Будая "Дизайн патерни – просто, як двері". Матеріал розміщується за домовленістю з автором.
Зверніть увагу на додаткові посиланняЯкщо вас цікавить...Головний розділСторінки, близькі за змістомзагрузка...
|
Сторінки, близькі за змістом Дозволяє доступатися почергово до елементів будь-якої колекції без вникання в суть її імплементації. ![]() Шаблони проектування програмного забезпечення (англ. software design patterns) — ефективні способи вирішення задач проектування програмного забезпечення. Шаблон не є закінченим зразком, який можна безпосередньо транслювати в програмний код. Об'єктно-орієнтований шаблон найчастіше є зразком вирішення проблеми і відображає відношення між класами та об'єктами, без вказівки на те, як буде зрештою реалізоване це відношення. |
|
Copyright © 2008—2026 Портал Знань.
При використанні матеріалів посилання, для інтернет-ресурсів — гіперпосилання, на Znannya.org обов'язкове.
Зв'язок
|
НТУУ "КПІ" Інженерія програмного забезпечення КПІ Лабораторія СЕТ |
|