行为型 迭代器模式

简介: 行为型 迭代器模式

迭代器的作用:遍历某一类相同元素的集合。

迭代器模式属于 行为型设计模式。

迭代器的思路: 在不改变底层元素的前提下,按照某种方式遍历集合中元素的值。

迭代器的实现:

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代替 模板机制代替了虚基函数处理引用的问题
目录
相关文章
|
2月前
|
设计模式 安全 Java
Java设计模式-迭代器模式(21)
Java设计模式-迭代器模式(21)
|
5月前
|
设计模式 Java
Java设计模式之迭代器模式详解
Java设计模式之迭代器模式详解
|
设计模式 XML 存储
设计模式-行为型模式:迭代器模式
设计模式-行为型模式:迭代器模式
|
6月前
|
设计模式 Java 数据挖掘
聊聊Java设计模式-迭代器模式
迭代器(Iterator)模式,也叫做游标(Cursor)模式。我们知道,在Java 容器中,为了提高容器遍历的方便性,我们利用迭代器把遍历逻辑从不同类型的集合类中抽取出来,从而避免向外部暴露集合容器的内部结构。
61 0
聊聊Java设计模式-迭代器模式
|
6月前
|
算法
行为型 访问者模式
行为型 访问者模式
57 0
|
设计模式 算法 Java
行为型设计模式06-迭代器模式
行为型设计模式06-迭代器模式
35 0
|
设计模式 存储 Java
迭代器模式
迭代器模式(Iterator Pattern)是一种行为型设计模式,它提供了一种顺序访问聚合对象中每个元素的方法,而不暴露其内部实现。
96 1
|
容器
关于迭代器模式我所知道的
关于迭代器模式我所知道的
50 0
|
JavaScript 前端开发
简单理解迭代器模式
这几天研究了一下迭代器模式,期间有一段时间经常搞不太懂一些概念与概念之间的关系,今天来整理一下。
125 0
|
设计模式 存储 容器
我学会了,迭代器模式
迭代器模式属于行为型模式,这个类型的设计模式总结出了 类、对象之间的经典交互方式,将类、对象的行为和使用解耦了,花式的去使用对象的行为来完成特定场景下的功能。
101 0
我学会了,迭代器模式