1、意图
Provide a way to access the elements of an aggregate objectsequentially without exposing its underlying representation.
2、适应性
Use the Iterator pattern
• to access an aggregate object's contents without exposing its internalrepresentation.
• to support multiple traversals of aggregate objects.
• to provide a uniform interface for traversing different aggregatestructures (that is, to support polymorphic iteration).
3、结构
4、示例代码
The part of the List, The List class provides a reasonably efficient way to support iteration through its public interface.
template <class Item>
class List {
public:
List(long size = DEFAULT_LIST_CAPACITY);
long Count() const;
Item& Get(long index) const;
// ...
};
To enabletransparent use of the different traversals we define an abstractIterator class, which defines the iterator interface.
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 subclass implementations.ListIterator is a subclass of Iterator.
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;
};
template <class Item>
ListIterator<Item>::ListIterator ( const List<Item>* aList )
: _list(aList), _current(0) { }
template <class Item>
void ListIterator<Item>::First ()
{
_current = 0;
}
// Next advances the current element:
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);
}
Using the iterators.
void PrintEmployees (Iterator<Employee*>& i) {
for (i.First(); !i.IsDone(); i.Next()){
i.CurrentItem()->Print();
}
}
List<Employee*>* employees;
// ...
ListIterator<Employee*> forward(employees);
ReverseListIterator<Employee*> backward(employees);
PrintEmployees(forward);
PrintEmployees(backward);
// SkipList ...
SkipList<Employee*>* employees;
// ...
SkipListIterator<Employee*> iterator(employees);
PrintEmployees(iterator);
Although this approach works, it would be better if we didn't have to committo a specific List implementation, namely SkipList. We can introduce an AbstractListclass to standardize the list interface for different list implementations. List and SkipList becomesubclasses of AbstractList.
template <class Item>
class AbstractList {
public:
virtual Iterator<Item>* CreateIterator() const = 0;
// ...
};
List overrides CreateIterator(Factory method) to return aListIterator object:
template <class Item>
Iterator<Item>* List<Item>::CreateIterator () const {
return new ListIterator<Item>(this);
// Now we're in a position to write the code for printingthe employees
// independent of a concrete representation.
// we know only that we have an AbstractList
AbstractList<Employee*>* employees;
// ...
Iterator<Employee*>* iterator = employees->CreateIterator();
PrintEmployees(*iterator);
delete iterator;
Making sure iterators get deleted. we'll provide an IteratorPtr that acts as a proxy for aniterator. It takes care of cleaning up the Iterator objectwhen it goes out of scope.
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;
};
// IteratorPtr lets us simplify our printing code:
AbstractList<Employee*>* employees;
// ...
IteratorPtr<Employee*> iterator(employees->CreateIterator());