最近在阅读levelDB源代码,看到了很典型的Iterator模式,这也是在设计模式中常用的模式之一,特意整理该博文,便于以后自己实践过程中借鉴,可以写出可读性更强的代码。

定义

Iterator模式(迭代器) 对象行为型模式

意图
提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。

适用性

  1. 访问一个聚合对象的内容而无需暴露它的内部表示
  2. 支持对聚合对象的多种遍历
  3. 为遍历不同的聚合结构提供一个统一的接口(支持多态迭代)

参与者

  1. Iterator(迭代器) 迭代器定义访问和遍历元素的接口
  2. ConcreteIterator(具体迭代器) 具体迭代器实现迭代器接口,对该聚合遍历时跟踪当前位置
  3. Aggregate(聚合) 聚合定义创建相应迭代器对象的接口
  4. ConcreteAggregate(具体聚合) 具体聚合实现创建相应迭代器的接口, 该操作返回ConcreteIterator的一个适当的实例。

levelDB的Iterator模式

Iterator定义

class Iterator {
 public:
     Iterator();
     virtual ~Iterator();
     virtual bool Valid() const = 0;
     virtual void SeekToFirst() = 0;
     virtual void SeekToLast() = 0;
     virtual void Seek(const Slice& target) = 0;
     virtual void Next() = 0;
     virtual void Prev() = 0;
     ......
 private:
     Cleanup cleanup_;
     ......
};

ConcreteIterator

class EmptyIterator : public Iterator
class MemTableIterator: public Iterator
class MergingIterator : public Iterator
class TwoLevelIterator: public Iterator 
class DBIter: public Iterator
class Block::Iter : public Iterator
class Version::LevelFileNumIterator:public Iterator

ConcreteAggregate(具体聚合)

//Block
class Block 
{
    public:
        Iterator* NewIterator(const Comparator* comparator);
};

Iterator* Block::NewIterator(const Comparator* cmp) {
    if (size_ < 2*sizeof(uint32_t)) {
        return NewErrorIterator(...);
    }
    const uint32_t num_restarts = NumRestarts();
    if (num_restarts == 0) {
        return NewEmptyIterator();
    } else {
        return new Iter(cmp, data_, restart_offset_, num_restarts);
    }
}

//MemTable
class MemTable 
{
public:
    Iterator* NewIterator();
};

Iterator* MemTable::NewIterator() {
    return new MemTableIterator(&table_);
}

总结

使用了Iterator设计模式就可以将复杂的实现抽象出来,而且便于扩展。这符合了面向接口编程的思想:使用者看到的是Iterator接口,而底层根据自己的需求实现特定的Iter

参考

  • 设计模式:可复用面向对象软件的基础

 

  1. 1. 为什么不符合STL的iterator规范
    2. 为什么iterator之间使用继承,而不是像STL一样使用模版/泛型。