迭代器的作用:遍历某一类相同元素的集合。
迭代器模式属于 行为型设计模式。
迭代器的思路: 在不改变底层元素的前提下,按照某种方式遍历集合中元素的值。
迭代器的实现:
1:前提: 需要一个集合元素类,一个集合类,需要一个迭代器类
2:迭代器中可以获取到集合类的对象,对该对象进行接口封装。
3:如何扩展迭代器模型: 可以用模板模型进行扩展
1: 《图解设计模式》中遍历书架中的书本为例子,UML图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XahJ4p33-1627281881798)(…\md文档相关图片\迭代器模式实例UML图.png)]
对上面的这幅图做进一步的说明,
- Aggregate表示集合的接口,书架实现该接口,所以书架必须要有迭代器的方法;
- Iterator表示集合的迭代器的接口,书架的迭代器实现它,需要用到书架具体对象调用相关的方法;
需要说明的是,此处的迭代器只有一种前向的迭代器,也可以定义后向遍历的迭代器。
认识: Aggregate和Iterator是抽象类,虚接口;
Bookshelf是实际的集合类的实现类。 ==》初始化迭代器类
BookShelfIterator 是对应bookshelf集合类对应的具体迭代器封装实现类。 ==》初始化时要传入集合类的对象
2:根据上文的理解,初步尝试实现迭代器的demo代码(C++):
//1:实现集合中单个元素的类 //2:实现迭代器的类,具体迭代器的类可以操作对应的集合类,用到集合类中的相关遍历方法 //如何实现迭代器中可以用到集合类对象的接口,需要传递 //3:实现集合的类,包含创建迭代器接口。 //简单的一个集合类,然后创建一个迭代器类,通过迭代器类控制集合的遍历访问集合中元素。 #include <iostream> #include <vector> using namespace std; class TestIterator; class TestVector{ public: //构造和析构 TestVector():m_itr(nullptr), count(0) {} ~TestVector() { if(m_itr != nullptr) { delete m_itr; m_itr = nullptr; } } //类本身的方法 插入元素和获取元素 void push(int d) { m_testvector.push_back(d); count++; } void pop() { m_testvector.pop_back(); count--; } int getCount() { return count; } int getData(int d) { if(d < count) { return m_testvector[d]; } return -1; } //这里定义创建迭代器的方法,通过迭代器控制数组元素的访问 TestIterator * CreateTestIterator() { if(m_itr == nullptr) { m_itr = new TestIterator(this); } return m_itr; } private: vector<int> m_testvector; TestIterator * m_itr; //这里为了对应释放 int count; }; //通过迭代器类调用对应的方法访问集合元素 这里用下标控制访问 class TestIterator { public: //要操作的集合的类和集合下标 TestIterator(TestVector * ts):m_ts(ts), curr(0) {} ~TestIterator() {} //判断是否有下一个元素 bool HasNext() { if(curr >= m_ts->getCount()) { return false; } return true; } //返回的其实是集合类中迭代器下一个元素 int Next() { int data = m_ts->getData(curr); curr++; return data; } //重置节点的信息 void reset() { curr=0; } private: TestVector* m_ts; int curr; }; int main() { //创建一个集合类 并塞入相关数据 TestVector * test = new TestVector(); test->push(5); test->push(8); test->push(6); test->push(7); test->push(3); test->push(2); cout<<"count:"<<test->getCount()<<endl; TestIterator *itr = test->CreateTestIterator(); int num = 0; //这里的元素是一个int,所以直接打印,可以有其他类型 while(itr->HasNext()) { cout<<" num "<<num <<"is "<<itr->Next()<<endl; num ++; } for(int i=0;i<test->getCount(); i++) { cout<<" i "<<i<<" is" <<test->getData(i)<<endl; } if(test != nullptr) { delete test; test= nullptr; } return 0; }
注意: 发现上述代码因为两个类相互引用,而无法编译通过。
3:思考解决引用编译不过的问题
可以用虚基函数来处理。
可以用C++模板定义来规避,直接用类型替代。
//上面的demo发现编译不通过,是类与类之间相关引用的原因,所以这里需要一个中间类来实现 //迭代器测试类初始化要用到 集合类,这里构造一个集合类的基类,实现迭代器的初始化测试 //集合类要用到迭代器类去做相关初始化 同样需要构造一个迭代器基础类,来供集合类接口调用 #include <iostream> #include <vector> using namespace std; class baseIterator{ public: virtual ~baseIterator() = default; virtual bool HasNext() = 0; virtual int Next() = 0; virtual void reset() = 0; }; //包含必要的集合类的方法,通过传入该对象实现迭代器的调用 class baseTestIterator{ public: virtual ~baseTestIterator() = default; virtual baseIterator * CreateTestIterator()= 0; virtual int getCount() = 0; virtual int getData(int d) = 0; }; class TestIterator: public baseIterator { public: //要操作的集合的类和集合下标 TestIterator(baseTestIterator * ts):m_ts(ts), curr(0) {} ~TestIterator() {} //判断是否有下一个元素 bool HasNext() { if(curr >= m_ts->getCount()) { return false; } return true; } //返回的其实是集合类中迭代器下一个元素 int Next() { int data = m_ts->getData(curr); curr++; return data; } //重置节点的信息 void reset() { curr=0; } private: baseTestIterator* m_ts; int curr; }; class TestVector: public baseTestIterator{ public: //构造和析构 TestVector():m_itr(nullptr), count(0) {} ~TestVector() { if(m_itr != nullptr) { delete m_itr; m_itr = nullptr; } } //类本身的方法 插入元素和获取元素 void push(int d) { m_testvector.push_back(d); count++; } void pop() { m_testvector.pop_back(); count--; } int getCount() { return count; } int getData(int d) { if(d < count) { return m_testvector[d]; } return -1; } //这里定义创建迭代器的方法,通过迭代器控制数组元素的访问 baseIterator * CreateTestIterator() { if(m_itr == nullptr) { m_itr = new TestIterator(this); } return m_itr; } private: vector<int> m_testvector; baseIterator * m_itr; //这里为了对应释放 int count; }; int main() { //创建一个集合类 并塞入相关数据 TestVector * test = new TestVector(); test->push(5); test->push(8); test->push(6); test->push(7); test->push(3); test->push(2); cout<<"count:"<<test->getCount()<<endl; baseIterator *itr = test->CreateTestIterator(); int num = 0; //这里的元素是一个int,所以直接打印,可以有其他类型 while(itr->HasNext()) { cout<<" num "<<num <<"is "<<itr->Next()<<endl; num ++; } for(int i=0;i<test->getCount(); i++) { cout<<" i "<<i<<" is " <<test->getData(i)<<endl; } if(test != nullptr) { delete test; test= nullptr; } return 0; } //C++中相关集合类数据结构的迭代器实现方式类似,只是增加了模板定义,next的处理用指针地址+1代替 模板机制代替了虚基函数处理引用的问题