迭代器模式(Iterator Pattern)是一种行为型设计模式,它提供了一种方法顺序访问聚合对象中的各个元素,而又不暴露该对象的内部表示。这种模式将遍历集合的责任从集合对象中分离出来,交给专门的迭代器对象,从而简化集合的接口和实现。

迭代器模式的核心角色

  1. 迭代器(Iterator):定义访问和遍历元素的接口
  2. 具体迭代器(Concrete Iterator):实现迭代器接口,跟踪遍历中的当前位置
  3. 聚合(Aggregate):定义创建相应迭代器对象的接口
  4. 具体聚合(Concrete Aggregate):实现创建相应迭代器的接口,返回具体迭代器实例

迭代器模式的实现示例

下面以"自定义集合"为例展示迭代器模式的实现,我们将创建一个支持迭代器的书架集合,用于存储和遍历书籍:

#include <iostream>
#include <string>
#include <vector>

// 前向声明
template <typename T>
class Iterator;

// 聚合接口
template <typename T>
class Aggregate {
public:
    virtual Iterator<T>* createIterator() = 0;
    virtual int getSize() const = 0;
    virtual T getItem(int index) const = 0;
    virtual void addItem(const T& item) = 0;
    virtual ~Aggregate() = default;
};

// 迭代器接口
template <typename T>
class Iterator {
public:
    virtual bool hasNext() const = 0;
    virtual T next() = 0;
    virtual ~Iterator() = default;
};

// 具体聚合:书架
class Book {
private:
    std::string name;

public:
    Book(const std::string& bookName) : name(bookName) {}
    std::string getName() const { return name; }
};

// 具体聚合:书架
class BookShelf : public Aggregate<Book> {
private:
    std::vector<Book> books;

public:
    int getSize() const override {
        return books.size();
    }

    Book getItem(int index) const override {
        return books[index];
    }

    void addItem(const Book& item) override {
        books.push_back(item);
    }

    // 创建迭代器
    Iterator<Book>* createIterator() override;
};

// 具体迭代器:书架迭代器
class BookShelfIterator : public Iterator<Book> {
private:
    const BookShelf* bookShelf;
    int index;

public:
    BookShelfIterator(const BookShelf* shelf) : bookShelf(shelf), index(0) {}

    bool hasNext() const override {
        return index < bookShelf->getSize();
    }

    Book next() override {
        Book book = bookShelf->getItem(index);
        index++;
        return book;
    }
};

// 实现BookShelf的createIterator方法
Iterator<Book>* BookShelf::createIterator() {
    return new BookShelfIterator(this);
}

// 客户端使用
int main() {
    // 创建书架并添加书籍
    BookShelf* bookShelf = new BookShelf();
    bookShelf->addItem(Book("设计模式"));
    bookShelf->addItem(Book("C++ Primer"));
    bookShelf->addItem(Book("算法导论"));
    bookShelf->addItem(Book("计算机网络"));

    // 获取迭代器并遍历
    Iterator<Book>* iterator = bookShelf->createIterator();
    std::cout << "书架上的书籍:" << std::endl;
    while (iterator->hasNext()) {
        Book book = iterator->next();
        std::cout << "- " << book.getName() << std::endl;
    }

    // 清理资源
    delete iterator;
    delete bookShelf;

    return 0;
}

迭代器模式的工作原理

  1. 聚合对象创建一个迭代器对象,迭代器保存了遍历所需的状态(如当前位置)
  2. 客户端通过迭代器的hasNext()方法检查是否还有元素
  3. 客户端通过迭代器的next()方法获取下一个元素并移动到下一个位置
  4. 聚合对象不需要暴露其内部结构(如数组、链表等),客户端只需通过迭代器接口访问元素

迭代器的常见类型

  • 内部迭代器:由迭代器控制遍历过程,客户端无法干预
  • 外部迭代器:由客户端控制遍历过程(如示例中的迭代器)
  • 正向迭代器:只能向前遍历(如示例中的迭代器)
  • 双向迭代器:可以向前和向后遍历
  • 随机访问迭代器:可以直接访问任意位置的元素

迭代器模式与其他模式的关系

  • 组合模式:通常结合迭代器模式使用,以便遍历组合对象的树形结构
  • 工厂方法模式:聚合对象创建迭代器的过程常用工厂方法模式

迭代器模式的应用场景

  1. 当需要访问一个聚合对象的元素,而又不想暴露其内部表示时
  2. 当需要为聚合对象提供多种遍历方式时
  3. 当需要为不同的聚合结构提供统一的遍历接口时

迭代器模式的优缺点

优点

  • 分离了集合对象的遍历行为,使集合对象更加简洁
  • 提供了统一的遍历接口,简化了客户端代码
  • 支持多种遍历方式,不同的迭代器可以实现不同的遍历逻辑
  • 便于在遍历过程中增加额外操作(如过滤、转换等)

缺点

  • 增加了类的数量,每一种集合可能需要对应一种迭代器
  • 对于简单的集合,使用迭代器可能显得过于繁琐
  • 在遍历过程中修改集合结构可能会导致迭代器失效

迭代器模式在C++标准库中有着广泛应用,std::vectorstd::list等容器都提供了迭代器支持,begin()end()方法返回迭代器,使客户端可以统一的方式遍历不同的容器。这种设计极大地提高了STL的灵活性和一致性。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐