Паттерны поведения
protected:
virtual bool Processltem(const Item&) = 0;
private:
Listlterator „iterator;
};
ListTraverser принимает экземпляр List в качестве параметра. Внутри
себя он использует внешний итератор List Iterator для выполнения обхо-
да. Операция Traverse начинает обход и вызывает для каждого элемента
операцию Processltem. Внутренний итератор может закончить обход, вер-
нув false из Processltem. Traverse сообщает о преждевременном завер-
шении обхода:
template
ListTraverser- ::ListTraverser (
List- * aList
) : _iterator(aList) { }
template
bool ListTraverser- ::Traverse () {
bool result = false;
for (
_iterator.First();
!_iterator.IsDone();
_iterator.Next()
) {
result = ProcessItem(_iterator.CurrentItem());
if (result == false) {
break;
}
}
return result;
}
Воспользуемся итератором ListTraverser для печати первых десяти слу-
жащих из списка. С этой целью надо породить подкласс от ListTraverser
и определить в нем операцию Process Item. Подсчитывать число напеча-
танных служащих будем в переменной экземпляра _count:
class PrintNEmployees : public ListTraverser {
public:
PrintNEmployees(List* aList, int n) :
ListTraverser(aList),
_ t o t a l ( n ) , _count(0) { }
protected:
bool ProcessltemtEmployee* const&);
private:
int _total;
int _count;
};
Паттерн Iterator
bool PrintNEmployees::ProcessItem (Employee* const& e) {
_count++;
e->Print();
return _count < _total;
}
Вот как
PrintNEmployees
печатает первые 10 служащих:
List* employees;
/ /
. . .
PrintNEmployees pa(employees, 10);
pa.Traverse();
Обратите внимание, что в коде клиента нет цикла итерации. Всю логику обхо-
да можно использовать повторно. В этом и состоит основное преимущество
внутреннего итератора. Работы, правда, немного больше, чем для внешнего
итератора, так как нужно определять новый класс. Сравните с программой,
где применяется внешний итератор:
ListIterator i(employees);
int count = 0;
for (i. First (); !i.IsDone() ; i.NextO) {
count++;
i.Currentltemf)->Print();
if (count >= 10) {
break;
}
}
Внутренние итераторы могут инкапсулировать разные виды итераций.
Например, FilteringListTraverser инкапсулирует итерацию, при ко-
торой обрабатываются лишь элементы, удовлетворяющие определенному
условию:
template
class FilteringListTraverser {
public:
FilteringListTraverser (List- * aList) ;
bool Traverse ( ) ;
protected:
virtual bool Processltemfconst Item&) = 0;
virtual bool Testltemt const Item&) = 0;
private:
Listlterator _iterator;
};
Интерфейс такой же, как у ListTraverser, если не считать новой функ-
ции-члена Test Item, которая и реализует проверку условия. В подклассах
Test Item замещается для задания конкретного условия.
Посредством операции Traverse выясняется, нужно ли продолжать обход,
основываясь на результате проверки:
Do'stlaringiz bilan baham: |