十六、Iterator(迭代器)
情景举例:
提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。
代码示例:
/* List的抽象父类
*/
template <class Item>
class List {
public:
List(long size = DEFAULT_LIST_CAPACITY);
/*
*/
Iterator<Item>* CreateIterator() const;
/*
*/
long Count() const;
Item& Get(long index) const;
// ...
};
/* Iterator的抽象父类。注意:不用将迭代器声明为链表的友元
*/
template <class Item>
class Iterator {
public:
virtual void First() = 0;
virtual void Next() = 0;
virtual bool IsDone() const = 0;
virtual Item CurrentItem() const = 0;
protected:
Iterator();
};
/* Iterator的子类。注意:其私有成员中有个List
*/
template <class Item>
class ListIterator : public Iterator<Item> {
public:
ListIterator(const List<Item>* aList);
virtual void First();
virtual void Next();
virtual bool IsDone() const;
virtual Item CurrentItem() const;
/*
*/
private:
const List<Item>* _list;
long _current;
};
/* 下面是ListIterator的实现
*/
template <class Item>
ListIterator<Item>::ListIterator (
const List<Item>* aList
) : _list(aList), _current(0) {
}
/*
*/
template <class Item>
void ListIterator<Item>::First () {
_current = 0;
}
/*
*/
template <class Item>
void ListIterator<Item>::Next () {
_current++;
}
/*
*/
template <class Item>
bool ListIterator<Item>::IsDone () const {
return _current >= _list->Count();
}
/*
*/
template <class Item>
Item ListIterator<Item>::CurrentItem () const {
if (IsDone()) {
throw IteratorOutOfBounds;
}
return _list->Get(_current);
}
/*下面是ReverseListIterator的接口。其实现与ListIterator类似,故略
*/
template <class Item>
class ReverseListIterator : public Iterator<Item> {
public:
ReverseListIterator(const List<Item>* aList);
virtual void First();
virtual void Next();
virtual bool IsDone() const;
virtual Item CurrentItem() const;
};
/*
*/
class Employee {
public:
void Print();
}
/*
*/
void PrintEmployees (Iterator<Employee*>& i) {
for (i.First(); !i.IsDone(); i.Next()) {
i.CurrentItem()->Print();
}
}
/* dummy中演示了如何使用Iterator
*/
void dummy () {
/*
*/
List<Employee*>* employees;
// ...
ListIterator<Employee*> forward(employees);
ReverseListIterator<Employee*> backward(employees);
PrintEmployees(forward);
PrintEmployees(backward);
/*
*/
}
template <class Item>
class SkipList : public List<Item> {
public:
};
template <class Item>
class SkipListIterator : public ListIterator<Item> {
public:
SkipListIterator(const List<Item>* aList);
void First();
void Next();
bool IsDone() const;
Item CurrentItem() const;
};
/* dummy2中演示如何使用新的SkipIterator,上面是必要的类的接口。
*/
void dummy2 () {
/*
*/
SkipList<Employee*>* employees;
// ...
SkipListIterator<Employee*> iterator(employees);
PrintEmployees(iterator);
/* 可以看到:Iterator依赖具体的List,即指不能进行多态迭代。dummy3中
想办法使用一个工厂方法解决这个问题。
*/
}
/* 工厂方法
*/
template <class Item>
class AbstractList {
public:
virtual Iterator<Item>* CreateIterator() const = 0;
// ...
};
/*
*/
template <class Item>
Iterator<Item>* List<Item>::CreateIterator () const {
return new ListIterator<Item>(this);
}
/* dummy3中不用指明具体的List也能使用Iterator
*/
void dummy3() {
/*
*/
// we know only that we have an AbstractList
AbstractList<Employee*>* employees;
// ...
Iterator<Employee*>* iterator = employees->CreateIterator();
PrintEmployees(*iterator);
delete iterator;
/* 可以看到:Iterator必须由主程序负责删除,这很容易出错,dummy4使用代
理方法解决这个问题
*/
}
/* Iterator代理类
*/
template <class Item>
class IteratorPtr {
public:
IteratorPtr(Iterator<Item>* i): _i(i) { }
~IteratorPtr() { delete _i; }
/*
*/
Iterator<Item>* operator->() { return _i; }
Iterator<Item>& operator*() { return *_i; }
private:
// disallow copy and assignment to avoid
// multiple deletions of _i:
IteratorPtr(const IteratorPtr&);
IteratorPtr& operator=(const IteratorPtr&);
private:
Iterator<Item>* _i;
};
/* dummy4则显得比较完美。dummy3与dummy4都不是模式必须的。
*/
void dummy4 () {
/*
*/
AbstractList<Employee*>* employees;
// ...
IteratorPtr<Employee*> iterator(employees->CreateIterator());
PrintEmployees(*iterator);
/*
*/
}
/* 下面是使用内部迭代器的例子,先是List抽象父类的接口。注意:有个Iterator私有变量
*/
template <class Item>
class ListTraverser {
public:
ListTraverser(List<Item>* aList);
bool Traverse();
protected:
virtual bool ProcessItem(const Item&) = 0;
private:
ListIterator<Item> _iterator;
};
/*
*/
template <class Item>
ListTraverser<Item>::ListTraverser (
List<Item>* aList
) : _iterator(aList) { }
/* Traverse方法的定义,实现了内部迭代。注意:其中ProcessItem方法是纯
虚函数,要由其子类来定义其具体实现。
*/
template <class Item>
bool ListTraverser<Item>::Traverse () {
bool result = false;
for (
_iterator.First();
!_iterator.IsDone();
_iterator.Next()
) {
result = ProcessItem(_iterator.CurrentItem());
/*
*/
if (result == false) {
break;
}
}
return result;
}
/* 一个使用该ListTraverser的子类,定义了ProcessItem的具体实现。
*/
class PrintNEmployees : public ListTraverser<Employee*> {
public:
PrintNEmployees(List<Employee*>* aList, int n) :
ListTraverser<Employee*>(aList),
_total(n), _count(0) { }
/*
*/
protected:
bool ProcessItem(Employee* const&);
private:
int _total;
int _count;
};
/*
*/
bool PrintNEmployees::ProcessItem (Employee* const& e) {
_count++;
e->Print();
return _count < _total;
}
/* dummy5演示了如何使用内部迭代器,并与外部迭代器做比较。可见内部迭代
器无需关心如何迭代循环。
*/
void dummy5 () {
/*
*/
List<Employee*>* employees;
// ...
PrintNEmployees pa(employees, 10);
pa.Traverse();
/*
*/
ListIterator<Employee*> i(employees);
int count = 0;
/*
*/
for (i.First(); !i.IsDone(); i.Next() ) {
count++;
i.CurrentItem()->Print();
/*
*/
if (count >= 10) {
break;
}
}
/*
*/
}
/* FilteringListTraverser则是另一个内部迭代器,仅处理通过测试的列表元素
*/
template <class Item>
class FilteringListTraverser {
public:
FilteringListTraverser(List<Item>* aList);
bool Traverse();
protected:
virtual bool ProcessItem(const Item&) = 0;
virtual bool TestItem(const Item&) = 0;
private:
ListIterator<Item> _iterator;
};
/*
*/
template <class Item>
void FilteringListTraverser<Item>::Traverse () {
bool result = false;
/*
*/
for (
_iterator.First();
!_iterator.IsDone();
_iterator.Next()
) {
if (TestItem(_iterator.CurrentItem())) {
result = ProcessItem(_iterator.CurrentItem());
/*
*/
if (result == false) {
break;
}
}
}
return result;
}
个人理解:
迭代器在面向对象系统中应用的相当普遍。其主要分为外部迭代器和内部迭代器,内部迭代器自己控制迭代方式,而外部迭代器则由外部控制。其实,建议看一遍STL的源码就能对迭代器有较深刻的认识。