设计模式学习笔记(十八)——Iterator迭代器

来源:互联网 发布:中国制造业发展数据 编辑:程序博客网 时间:2024/05/16 17:28

十六、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则显得比较完美。dummy3dummy4都不是模式必须的。
*/
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的源码就能对迭代器有较深刻的认识。