Частина тексту файла (без зображень, графіків і формул):
Міністерство освіти та науки України
Національний університет ”Львівська політехніка”
ІКТА
Кафедра СКС
Лабораторна робота №3
з дисципліни «Проектування контролерів периферійних пристроїв »
Львів 2014
Тема: Ознайомлення з Патерном Ітератор — Iterator
Мета: Навчитися реалізовувати та застосовувати патерн Ітератор — Iterator
Уявіть, що ви розробник статегічної воєнної гри. Армія має складну структуру: вона складається із героя і трьох груп. Коли генерал видає указ і ресурси щоб полікувати всіх воїнів (герой також є воїном), ви хочете проітерувати по всіх солдатах і викликати метод Treat() на кожному екземплярі. Як це можна зробити легко і без вникання в структуру армії?
Ітератор дозволяє доступатися почергово до елементів будь-якої колекції без вникання в суть її імплементації.
Таким чином в застосуванні до нашої проблеми, ми хочемо щоб SoldiersIterator «пробігся» по всіх солдатах. Код нище показує використання Ітератора.
var iterator = new SoldiersIterator(earthArmy);
while (iterator.HasNext())
{
var currSoldier = iterator.Next();
currSoldier.Treat();
}
Як бачимо, ми отримали екземпляр класу ітератора SoldiersIterator. І простим циклом проходимося по всіх солдатах армії. Це дуже легко, що і є основним завданням ітератора.Армія складається із одного героя і може містити багато груп, кожна із яких може містити багато солдатів. Отже, як ми бачимо, сктуктура армії складна і деревовидна. Код нижче показує створення армії:
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) і основна різниця полягає в тому, що він має вищий початковий рівень здоров’я.
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)
{
}
}
То ж, якщо ми можемо рухатися по складній колекції так легко, де ж вся складність? Звісно, вона інкапсульована в конкретному класі ітератора.
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;
}
}
Цей приклад дещо відхиляється від стандартного. Я собі поставив за мету підкреслити головне завдання, яке вирішує паттерн. Головною різницею між моїм поясненням і тоннами інших пояснень є те, що стандартні є більш абстраговані. Я створював потрібний нам ітератор таким чином:
var iterator = new SoldiersIterator(earthArmy);
Але зазвичай створення ітератора також інкапсулюється під методом агрегата. Це потрібно в тих ситуаціях, коли ми хочемо мати декілька різних ітераторів (скажімо, ще один тільки для героїв). Мій код міг би виглядати так:
AbstractIterator iterator = AbstractArmy.GetSoldiersIterator();
var list = new List<int>();
// GetEnumerator це метод інтерфейсу IEnumerable (агрегат)
var enumerator = list.GetEnumerator();
// MoveNext метод інтерфейсу IEnumerator і буде методом ітератора
enumerator.MoveNext();
Ви не можете залишити коментар. Для цього, будь ласка, увійдіть
або зареєструйтесь.
Ділись своїми роботами та отримуй миттєві бонуси!
Маєш корисні навчальні матеріали, які припадають пилом на твоєму комп'ютері? Розрахункові, лабораторні, практичні чи контрольні роботи — завантажуй їх прямо зараз і одразу отримуй бали на свій рахунок! Заархівуй всі файли в один .zip (до 100 МБ) або завантажуй кожен файл окремо. Внесок у спільноту – це легкий спосіб допомогти іншим та отримати додаткові можливості на сайті. Твої старі роботи можуть приносити тобі нові нагороди!