Iterator 迭代器模式

      Iterator 迭代器模式:提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该对象的内部表示,又称游标(Cursor)。该模式的应用应该十分熟悉了,C++ 标准库 STL 中不同的容器都提供了相同的迭代器接口。这一模式的关键思想是将对列表的访问和遍历从列表对象中分离出来并放入一个迭代器(iterator)对象中。迭代器类定义了一个访问列表元素的接口,迭代器对象负责跟踪当前的元素,即它知道哪些元素已经遍历过了。

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

Iterator 的通用结构如下:

Iterator

参与者

Iterator:迭代器定义访问和遍历元素的接口。

ConcreteIterator:具体迭代器实现迭代器接口。对该聚合遍历时跟踪当前位置。

Aggregate:聚合定义创建相应迭代器对象的接口。

ConcreteAggregate:具体聚合实现创建相应迭代器的接口,该操作返回 ConcreteIterator 的一个适当的实例。

实现时应该注意:

1.谁控制迭代器,不由客户控制迭代时,称为外部迭代器(external iterator),而当由迭代器控制时,称为内部迭代器(internal iterator)。使用外部迭代器,客户必须主动推进遍历的步伐,显式地向迭代器请求下一个元素。相反,使用内部迭代器时,客户只需提交一个执行请求,而迭代器将对聚合中的每一个元素实施该操作。 外部迭代器比内部迭代器更灵活。

2.谁定义遍历算法,聚合本身可以定义遍历算法,并在遍历过程中用迭代器来存储当前迭代的状态,这种迭代器称为一个游标,因为它仅用来指示当前位置。如果由迭代器负责遍历算法,那么将易于在相同的聚合上使用不同的迭代算法,同时也易于在不同的聚合上重用相同的算法。但同时,将遍历算法放入迭代器中会破坏聚合的封装性。

3.迭代器的健壮性非常重要,一个健壮的迭代器(robust iterator)保证插入和删除操作不会干扰遍历,且不需拷贝该聚合。

4.在 C++ 中使用多态的迭代器,使用多态迭代器是有代价的。它们要求用一个 Factory Method 动态的分配迭代器对象。因此仅当必须多态时才使用它们,否则使用在栈中分配内存的具体的迭代器。多态迭代器有另一个缺点:客户必须负责删除它们。Proxy 为此提供了一种补救方法,我们可以使用一个栈分配的 Proxy 作为实际迭代器的中间代理。该代理在其析构器中删除该迭代器。这样当该代理生命周期结束时,实际迭代器将同它一起释放,即使在发生异常时,该代理机制能保证正确地清除迭代器对象,这就是著名的C++“资源分配即初始化”技术的一个应用。

5.空迭代器,一个空迭代器(NullIterator)是一个退化的迭代器,它有助于处理边界条件。一个 NullIterator 总是已经完成了遍历,即它的 IsDone 操作总是返回 true。等还有其它比较复杂的注意事项。

Iterator 迭代器模式示例代码如下:

下面的代码分别示例了:1.正向迭代器;2.反向迭代器;3.迭代器代理;4.内部迭代器;5内部迭代器,过滤器;

//Aggregate.h 容器类

   1:   
   2:  #pragma once
   3:   
   4:  template
  
  
   5:  class Iterator;
   6:   
   7:  // 聚集的抽象基类
   8:  template
  
  
   9:  class Aggregate
  10:  {
  11:  public:
  12:      virtual ~Aggregate(){    }
  13:   
  14:      //为避免限定于一种特定的聚集实现迭代器, 实现多态
  15:      //Aggregate 定义一个 Factory Method
  16:      //各聚集子类重定义这个方法以返回相应的迭代器
  17:      virtual Iterator
  
  
   
   * CreateIterator() = 0;     
   
   //默认创建正向迭代器
  
  
  18:   
  19:      //正向迭代器和反向迭代器, 只为示例,实际并不这样实现
  20:      virtual Iterator
  
  
   
   * CreateForwardIterator()
   
   //正向迭代器
  
  
  21:      {
  22:          return 0;
  23:      }
  24:      virtual Iterator
  
  
   
   * CreateReverseIterator()
   
   //反向迭代器
  
  
  25:      {
  26:          return 0;
  27:      }
  28:      virtual int GetSize() const = 0;
  29:      virtual T GetItem(int nIndex) const = 0;
  30:  protected:
  31:      Aggregate(){    }
  32:  };
  33:   
  34:  // 一个具体的聚集类,定义相应迭代器对象的接口,这里是用数组表示
  35:  // 具体聚集实现创建相应迭代器的接口,并返回具体迭代器的实例
  36:  template
  
  
  37:  class ConcreteAggregate : public Aggregate
  
  
  38:  {
  39:  public:
  40:      ConcreteAggregate(int nSize)
  41:          : m_nSize(nSize), m_pData(NULL)
  42:      {
  43:          m_pData = new T[m_nSize];
  44:          
  45:          for (int i = 0; i < nSize; ++i)
  46:          {
  47:              m_pData[i] = i;
  48:          }
  49:      }
  50:      virtual ~ConcreteAggregate()
  51:      {
  52:          delete [] m_pData;
  53:          m_pData = NULL;
  54:          std::cout << "~ConcreteAggregate()" << std::endl;
  55:      }
  56:      //默认创建一个正向迭代器
  57:      Iterator
  
  
   
   * CreateIterator()
  
  
  58:      {
  59:          return new ForwardIterator
  
  
   
   (
   
   this);
  
  
  60:      }
  61:      Iterator
  
  
   
   * CreateForwardIterator()
  
  
  62:      {
  63:          return new ForwardIterator
  
  
   
   (
   
   this);
  
  
  64:      }
  65:      //创建一个反向迭代器
  66:      Iterator
  
  
   
   * CreateReverseIterator()
  
  
  67:      {
  68:          return new ReverseIterator
  
  
   
   (
   
   this);
  
  
  69:      }
  70:      virtual int GetSize() const 
  71:      {
  72:          return m_nSize;
  73:      }
  74:      virtual T GetItem(int nIndex) const
  75:      {
  76:          if (nIndex < m_nSize)
  77:          {
  78:              return m_pData[nIndex];
  79:          }
  80:          else
  81:          {
  82:              return -1;
  83:          }
  84:      }
  85:  private:
  86:      int m_nSize;
  87:      T  *m_pData;
  88:  };

//Iterator.h 不同的迭代器类

   1:   
   2:  #pragma once
   3:  #include 
  
  
   4:   
   5:  template
  
  
   6:  class Aggregate;
   7:   
   8:  // 迭代器的抽象基类
   9:  template
  
  
  10:  class Iterator
  11:  {
  12:  public:
  13:      virtual ~Iterator(){}
  14:   
  15:      //定义访问和遍历元素的接口
  16:      //First, Next, IsDone, CurrentItem
  17:      virtual void First()          = 0;   //将迭代器指向聚集第一个元素
  18:      virtual void Next()              = 0;   //将迭代器指向当前的下一个元素
  19:      virtual bool IsDone() const      = 0;   //是否已经遍历完毕
  20:      virtual T CurrentItem() const = 0;   //返回聚集当前元素
  21:  protected:
  22:      Iterator(){    };
  23:  };
  24:   
  25:  //1. 针对具体聚集的迭代器类, 正向迭代器
  26:  // 访问 ConcreateAggregate 容器类的迭代器类
  27:  // 实现迭代器接口,对聚合遍历时跟踪当前位置
  28:  template
  
  
  29:  class ForwardIterator : public Iterator
  
  
  30:  {
  31:  public:
  32:      ForwardIterator(Aggregate
  
  
   
   * pAggregate)
  
  
  33:          : m_pConcreteAggregate(pAggregate), m_nIndex(0)
  34:      {    }
  35:      virtual ~ForwardIterator(){ 
  36:          m_pConcreteAggregate = NULL; 
  37:          std::cout << "~ForwardIterator()" << std::endl;
  38:      }
  39:   
  40:      //First, Next, IsDone, CurrentItem
  41:      virtual void First(){ m_nIndex = 0; }
  42:      virtual void Next(){  ++m_nIndex;   }
  43:      virtual bool IsDone() const 
  44:      {
  45:          return m_nIndex == m_pConcreteAggregate->GetSize();
  46:      }
  47:      virtual T CurrentItem() const
  48:      {
  49:          return m_pConcreteAggregate->GetItem(m_nIndex);
  50:      }
  51:  private:
  52:      Aggregate
  
  
   
     *m_pConcreteAggregate;
  
  
  53:      int                     m_nIndex;
  54:  };
  55:   
  56:  //2. 具体的迭代器, 反向迭代器
  57:  template
  
  
  58:  class ReverseIterator : public Iterator
  
  
  59:  {
  60:  public:
  61:      ReverseIterator(Aggregate
  
  
   
   * pAggregate)
  
  
  62:          : m_pConcreteAggregate(pAggregate)
  63:      {    
  64:          m_nIndex = m_pConcreteAggregate->GetSize() - 1;
  65:      }
  66:      virtual ~ReverseIterator(){
  67:          m_pConcreteAggregate = NULL;
  68:          std::cout << "~ReverseIterator()" << std::endl;
  69:      }
  70:      //First, Next, IsDone, CurrentItem
  71:      void First()
  72:      {
  73:          m_nIndex = m_pConcreteAggregate->GetSize() - 1;
  74:      }
  75:      void Next(){   m_nIndex--; }
  76:      bool IsDone() const { return m_nIndex < 0; }
  77:      T CurrentItem() const
  78:      {
  79:          return m_pConcreteAggregate->GetItem(m_nIndex);
  80:      }
  81:  private:
  82:      Aggregate
  
  
   
     *m_pConcreteAggregate;
  
  
  83:      int                     m_nIndex;
  84:  };
  85:   
  86:  //3. 迭代器代理
  87:  /*
  88:  *注意 CreateIterator 返回的是一个动态分配的迭代器对象.在使用完之后,
  89:  *必须删除这个迭代器,否则会造成内存泄漏.
  90:  *为方便客户,我们提供一个 IeratorPtr 作为迭代器的代理, 这个机制可以
  91:  *保证在 Iterator对象离开作用域时清除它. IteratorPtr 总是在栈上分配
  92:  *(只需定义私有的 new 和 delete 操作符, 不需要附加实现).
  93:  *IteratorPtr 重载了操作符 -> 和 *,使得可将 IteratorPtr 用作一个指向
  94:  *迭代器的指针.IteratorPtr 的成员都实现为内联的,不会产生任何额外开销.
  95:  */
  96:  template
  
  
  97:  class IteratorPtr
  98:  {
  99:  public:
 100:      IteratorPtr(Iterator
  
  
   
   * i): _i(i){    }
  
  
 101:      ~IteratorPtr()
 102:      {
 103:          delete _i; 
 104:          std::cout << "~IteratorPtr()" << std::endl;
 105:      }
 106:   
 107:      Iterator
  
  
   
   * 
   
   operator->(){ 
   
   return _i;  }
  
  
 108:      Iterator
  
  
   
   & 
   
   operator*() { 
   
   return *_i; }
  
  
 109:  private:
 110:      //disallow copy and assignment to avoid multiple deletion of _i
 111:      IteratorPtr(const IteratorPtr&);
 112:      IteratorPtr& operator=(const IteratorPtr&);
 113:  private:
 114:      Iterator
  
  
   
   * _i;
  
  
 115:  };
 116:  //IteratorPtr 简化了打印代码: 假设有一个指向 Employee* 的雇员列表
 117:  //Aggregate
   
   
    
    * employees;
   
   
 118:  //IteratorPtr
   
   
    
     iterator(employee->CreateIterator());
   
   
 119:  //PrintEmployees(*iterator);
 120:  //*/
 121:   
 122:  //
 123:  //4. 内部迭代器示例
 124:  //一个内部的或被动的 ListIterator 类
 125:  //此时由迭代器来控制迭代,并对列表中的每一个元素施行同一个操作
 126:  /*
 127:    ListTraverser 以一个 Aggregate 实例为参数,在内部,它使用一个外部
 128:    ForwardIterator 进行遍历. Traverse 启动遍历并对每一元素项调用
 129:    ProcessItem 操作. 内部迭代器可在某次 ProcessItem 操作返回 false 
 130:    时提前终止本次遍历.而Traverse返回一个布尔值指示本次遍历是否提前终止. 
 131:   */
 132:  template
  
  
 133:  class AggregateTraverser
 134:  {
 135:  public:
 136:      AggregateTraverser(Aggregate
  
  
   
   * aggregate)
  
  
 137:          :_iterator(aggregate){    }
 138:      virtual bool Traverse()
 139:      {
 140:          bool result = false;
 141:          for(_iterator.First(); !_iterator.IsDone(); _iterator.Next())
 142:          {
 143:              result = ProcessItem(_iterator.CurrentItem());
 144:              if(result == false)
 145:              {
 146:                  break;
 147:              }
 148:          }
 149:          std::cout << std::endl;
 150:          return result;
 151:      }
 152:  protected:
 153:      virtual bool ProcessItem(const T& e) = 0;
 154:  private:
 155:      ForwardIterator
  
  
   
    _iterator;
  
  
 156:  };
 157:   
 158:  //内部迭代器的实现要比外部迭代器复杂
 159:  //为使用一个 AggregateTraverser 来打印具体的聚集列表,必须定义
 160:  //一个AggregateTraverser 的子类并重定义其 ProcessItem 操作
 161:  //这里定义一个打印 Aggregate
   
   
    
     列表的子类示例
   
   
 162:  class PrintIntTraverser : public AggregateTraverser<int>
 163:  {
 164:  public:
 165:      PrintIntTraverser(Aggregate<int>* aggre, int n)
 166:          : AggregateTraverser<int>(aggre),_total(n),_count(0)
 167:      {    }
 168:  protected:
 169:      bool ProcessItem(const int& e)
 170:      {
 171:          _count++;
 172:          std::cout << e << " ";
 173:          return _count < _total;
 174:      }
 175:  private:
 176:      int _total;
 177:      int _count;
 178:  };
 179:  //打印: 这里客户不需要如何进行迭代循环,整个迭代器可以重用
 180:  //这是内部迭代器的主要优点,其实现要比外部迭代器复杂一些
 181:  //List
   
   
    
    * employees;
   
   
 182:  //PrintIntTraverser pa(employees, employees->GetSize());
 183:  //pa.Traverse();
 184:   
 185:   
 186:  //5. 内部迭代器2
 187:  //内部迭代器可以封装不同类型的迭代, 例如, FilteringListTraverser
 188:  //封装的迭代仅处理能通过测试的那些列表元素:
 189:  template<class T>
 190:  class FilteringAggregateTraverser
 191:  {
 192:  public:
 193:      FilteringAggregateTraverser(Aggregate
  
  
   
   * aggre)
  
  
 194:          :_iterator(aggre){    }
 195:   
 196:      //这个类接口除了增加了用于测试的成员函数 TestItem 外与
 197:      //AggregateTraverser 相同,它的子类将重定义 TestItem 以指定所需的测试.
 198:      bool Traverse()
 199:      {
 200:          bool result = false;
 201:          for(_iterator.First(); !_iterator.IsDone(); _iterator.Next())
 202:          {
 203:              if(TestItem(_iterator.CurrentItem()))
 204:              {
 205:                  result = ProcessItem(_iterator.CurrentItem());
 206:                  if(result == false)
 207:                      break;
 208:              }
 209:          }
 210:          return result;
 211:      }
 212:  protected:
 213:      virtual bool ProcessItem(const T&) = 0;
 214:      virtual bool TestItem(const T&) = 0;
 215:  private:
 216:      ForwardIterator
  
  
   
    _iterator;
  
  
 217:  };
 218:   
 219:  //这里定义一个遍历 Aggregate
   
   
    
     子类, 过滤元素小于 2 的元素 
   
   
 220:  class Upper2Traverser : public FilteringAggregateTraverser<int>
 221:  {
 222:  public:
 223:      Upper2Traverser(Aggregate<int>* aggre, int n)
 224:          : FilteringAggregateTraverser<int>(aggre),_total(n),_count(0)
 225:      {    }
 226:  protected:
 227:      bool ProcessItem(const int& e)
 228:      {
 229:          _count++;
 230:          std::cout << e << " ";
 231:          return _count < _total;
 232:      }
 233:      virtual bool TestItem(const int& e)
 234:      {
 235:          return e > 2 ;
 236:      }
 237:  private:
 238:      int _total;
 239:      int _count;
 240:  };
 241:  //*/

//test.cpp

   1:   
   2:  #include "Iterator.h"
   3:  #include "aggregate.h"
   4:  #include 
  
  
   5:   
   6:  template
  
  
   7:  void PrintAggregate(Iterator
  
  
   
   & i)
  
  
   8:  {
   9:      for(i.First(); !i.IsDone(); i.Next())
  10:      {
  11:          std::cout << i.CurrentItem() << " ";
  12:      }
  13:      std::cout << std::endl;
  14:  }
  15:   
  16:  int main()
  17:  {
  18:      Aggregate<int>* pAggregate = new ConcreteAggregate<int>(10);
  19:   
  20:      //正向迭代器
  21:      Iterator<int>*  pIterator = pAggregate->CreateForwardIterator();
  22:      std::cout << "Now, the ForwardIterator: " << std::endl;
  23:      PrintAggregate(*pIterator);    
  24:      //或者自己操作迭代器,如下
  25:      for (pIterator->First(); !pIterator->IsDone(); pIterator->Next())
  26:      {
  27:          std::cout << pIterator->CurrentItem() << " ";
  28:      }
  29:      std::cout << std::endl;
  30:      //*/
  31:      
  32:      //反向迭代器
  33:      std::cout << "Now, the ReverseIterator: " << std::endl;
  34:      Iterator<int>*  pReverseIter = pAggregate->CreateReverseIterator();
  35:      PrintAggregate(*pReverseIter);
  36:   
  37:      //迭代器代理
  38:      {    //加上 { }, 演示迭代器代理的功能
  39:          IteratorPtr<int> iterPtr(pAggregate->CreateForwardIterator());
  40:          std::cout << "Now, the IteratorPtr: " << std::endl;
  41:          PrintAggregate(*iterPtr);
  42:      }//IterPtr 作用域至此结束
  43:      std::cout << "--------IteratorPtr 在离开作用域, 自动删除了真正的迭代器------"
  44:          << std::endl << std::endl;
  45:   
  46:      //内部迭代器
  47:      std::cout << "Now, the Inner Iterator: " << std::endl;
  48:      PrintIntTraverser pt(pAggregate, pAggregate->GetSize());
  49:      pt.Traverse();
  50:      std::cout << std::endl;
  51:   
  52:      //内部迭代器2, 过滤器示例
  53:      std::cout << "Now, the Filter Iterator: " << std::endl;
  54:      Upper2Traverser upt(pAggregate, pAggregate->GetSize());
  55:      upt.Traverse();
  56:      std::cout << std::endl << std::endl;
  57:      
  58:   
  59:      delete pIterator;
  60:      delete pReverseIter;
  61:      delete pAggregate;
  62:   
  63:      return EXIT_SUCCESS;
  64:  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值