设计模式(18)迭代器模式

迭代器模式简介

在C++标准库中,有专门的迭代器的额库,这里的迭代器模式与标准库中的迭代器功能差不多,都是对一个包含有许多个对象实例的集合进行访问和获取,另外要取集合的首位元素,末位元素,在某个位置的元素等。
针对这种集合对象的遍历,迭代器模式是一种很有效的解决方案,在实际工作中使用频率也很高。

迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。

迭代器模式结构

在这里插入图片描述
迭代器模式结构中包含聚合和迭代器两个层次的结构。为方便扩展,迭代器模式常常和工厂方法模式结合。由图可知,迭代器模式有以下几个角色:

  • Iterator(抽象迭代器):声明了访问和遍历聚合对象元素的接口,如first()方法用于访问聚合对象中第一个元素,next()方法用于访问下一个元素,hasNext()判断是否还有下一个元素,currentItem()方法用于获取当前元素。
  • ConcreteIterator(具体迭代器):实现抽象迭代器声明的方法,通常具体迭代器中会专门用一个变量(称为游标)来记录迭代器在聚合对象中所处的位置。
  • Aggregate(抽象聚合类):用于存储和管理元素对象,声明一个创建迭代器的接口,其实是一个抽象迭代器工厂的角色。
  • ConcreteAggregate(具体聚合类):实现了方法createIterator(),该方法返回一个与该具体聚合类对应的具体迭代器ConcreteIterator的实例。

迭代器模式代码实例

#include <iostream>

using namespace std;

typedef struct tagNode
{
    
    
  int value;
  tagNode *pNext;
} Node;

class JTList
{
    
    
public:
  JTList() : m_pHead(NULL), m_pTail(NULL){
    
    };
  JTList(const JTList &);
  ~JTList();
  JTList &operator=(const JTList &);

  long GetCount() const;
  Node *Get(const long index) const;
  Node *First() const;
  Node *Last() const;
  bool Includes(const int &) const;

  void Append(const int &);
  void Remove(Node *pNode);
  void RemoveAll();

private:
  Node *m_pHead;
  Node *m_pTail;
  long m_lCount;
};

class Iterator
{
    
    
public:
  virtual void First() = 0;
  virtual void Next() = 0;
  virtual bool IsDone() const = 0;
  virtual Node *CurrentItem() const = 0;
};

class JTListIterator : public Iterator
{
    
    
public:
  JTListIterator(JTList *pList) : m_pJTList(pList), m_pCurrent(NULL) {
    
    }

  virtual void First();
  virtual void Next();
  virtual bool IsDone() const;
  virtual Node *CurrentItem() const;

private:
  JTList *m_pJTList;
  Node *m_pCurrent;
};

JTList::~JTList()
{
    
    
  Node *pCurrent = m_pHead;
  Node *pNextNode = NULL;
  
  while (pCurrent)
  {
    
    
    pNextNode = pCurrent->pNext;
    delete pCurrent;
    pCurrent = pNextNode;
  }
}

long JTList::GetCount() const
{
    
    
  return m_lCount;
}

Node *JTList::Get(const long index) const
{
    
    
  // The min index is 0, max index is count - 1
  if (index > m_lCount - 1 || index < 0)
  {
    
    
    return NULL;
  }

  int iPosTemp = 0;
  Node *pNodeTemp = m_pHead;
  while (pNodeTemp)
  {
    
    
    if (index == iPosTemp++)
    {
    
    
      return pNodeTemp;
    }
    pNodeTemp = pNodeTemp->pNext;
  }
  return NULL;
}

Node *JTList::First() const
{
    
    
  return m_pHead;
}

Node *JTList::Last() const
{
    
    
  return m_pTail;
}

bool JTList::Includes(const int &value) const
{
    
    
  Node *pNodeTemp = m_pHead;
  while (pNodeTemp)
  {
    
    
    if (value == pNodeTemp->value)
    {
    
    
      return true;
    }
    pNodeTemp = pNodeTemp->pNext;
  }
  return false;
}

void JTList::Append(const int &value)
{
    
    
  // Create the new node
  Node *pInsertNode = new Node;
  pInsertNode->value = value;
  pInsertNode->pNext = NULL;

  // This list is empty
  if (m_pHead == NULL)
  {
    
    
    m_pHead = m_pTail = pInsertNode;
  }
  else
  {
    
    
    m_pTail->pNext = pInsertNode;
    m_pTail = pInsertNode;
  }
  ++m_lCount;
}

void JTList::Remove(Node *pNode)
{
    
    
  if (pNode == NULL || m_pHead == NULL || m_pTail == NULL)
  {
    
    
    return;
  }

  if (pNode == m_pHead) // If the deleting node is head node
  {
    
    
    Node *pNewHead = m_pHead->pNext;
    m_pHead = pNewHead;
  }
  else
  {
    
    
    // To get the deleting node's previous node
    Node *pPreviousNode = NULL;
    Node *pCurrentNode = m_pHead;
    while (pCurrentNode)
    {
    
    
      pPreviousNode = pCurrentNode;
      pCurrentNode = pCurrentNode->pNext;
      if (pCurrentNode == pNode)
      {
    
    
        break;
      }
    }

    // To get the deleting node's next node
    Node *pNextNode = pNode->pNext;

    // If pNextNode is NULL, it means the deleting node is the tail node, we should change the m_pTail pointer
    if (pNextNode == NULL)
    {
    
    
      m_pTail = pPreviousNode;
    }

    // Relink the list
    pPreviousNode->pNext = pNextNode;
  }

  // Delete the node
  delete pNode;
  pNode = NULL;
  --m_lCount;
}

void JTList::RemoveAll()
{
    
    
  delete this;
}

void JTListIterator::First()
{
    
    
  m_pCurrent = m_pJTList->First();
}

void JTListIterator::Next()
{
    
    
  m_pCurrent = m_pCurrent->pNext;
}

bool JTListIterator::IsDone() const
{
    
    
  return m_pCurrent == m_pJTList->Last()->pNext;
}

Node *JTListIterator::CurrentItem() const
{
    
    
  return m_pCurrent;
}

int main()
{
    
    
  JTList *pJTList = new JTList;
  pJTList->Append(10);
  pJTList->Append(20);
  pJTList->Append(30);
  pJTList->Append(40);
  pJTList->Append(50);
  pJTList->Append(60);
  pJTList->Append(70);
  pJTList->Append(80);
  pJTList->Append(90);
  pJTList->Append(100);

  Iterator *pIterator = new JTListIterator(pJTList);

  // Print the list by JTListIterator
  for (pIterator->First(); !pIterator->IsDone(); pIterator->Next())
  {
    
    
    cout << pIterator->CurrentItem()->value << "->";
  }
  cout << "NULL" << endl;

  // Test for removing
  Node *pDeleteNode = NULL;
  for (pIterator->First(); !pIterator->IsDone(); pIterator->Next())
  {
    
    
    pDeleteNode = pIterator->CurrentItem();
    if (pDeleteNode->value == 100)
    {
    
    
      pJTList->Remove(pDeleteNode);
      break;
    }
  }

  // Print the list by JTListIterator
  for (pIterator->First(); !pIterator->IsDone(); pIterator->Next())
  {
    
    
    cout << pIterator->CurrentItem()->value << "->";
  }
  cout << "NULL" << endl;

  delete pIterator;
  delete pJTList;

  return 0;
}

迭代器模式总结

优点:

  • 支持以不同的方式遍历一个聚合对象,在同一个聚合对象上可以定义多个遍历方式。
  • 简化了聚合类,使得聚合类的职责更加单一;
  • 迭代器模式中引入抽象层,易于增加新的迭代器类,便于扩展,符合开闭原则。

缺点:

  • 将聚合类中存储对象和管理对象的职责分离,增加新的聚合类时同样需要考虑增加对应的新的迭代器类,类的个数成对增加,不利于系统管理和维护;
  • 设计难度较大,需要充分考虑将来系统的扩展。

适用环境:

以下场景可以考虑使用迭代器模式:

  • 访问一个聚合对象而无需暴露它的内部结构;
  • 需要为一个聚合对象提供多种遍历方法。

おすすめ

転載: blog.csdn.net/qq_24649627/article/details/115484110