《设计模式的艺术》笔记 - 迭代器模式

介绍

迭代器模式提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示,其别名为游标(Cursor)。迭代器模式是一种对象行为型模式。

实现

myclass.h

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H

#include <iostream>
#include <unordered_map>
#include <atomic>
#include <vector>
#include <memory>
#include <list>

class Object {
public:
    Object(int id);
    int getId();
private:
    int m_id;
};

class Iterator {
public:
    virtual void first() = 0;
    virtual void next() = 0;
    virtual bool hasNext() = 0;
    virtual Object *currentItem() = 0;
};

class Aggregate {
public:
    virtual Iterator *createIterator() = 0;
};

class ConcreteAggregate : public Aggregate {
public:
    ~ConcreteAggregate();
    Iterator *createIterator() override;
    uint32_t size();
    Object *getObject(int index);
    void pushBack(Object *obj);
private:
    std::vector<Object *> m_objects;
};

class ConcreteIterator : public Iterator {
public:
    ConcreteIterator(ConcreteAggregate *mObjects);

    void first() override;

    void next() override;

    bool hasNext() override;

    Object *currentItem() override;

private:
    ConcreteAggregate *m_objects;
    int m_cursor;
};



#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#include "myclass.h"
#include <thread>
#include <unistd.h>
#include <sstream>

Object::Object(int id) {
    m_id = id;
}

int Object::getId() {
    return m_id;
}

Iterator *ConcreteAggregate::createIterator() {
    return new ConcreteIterator(this);
}

ConcreteIterator::ConcreteIterator(ConcreteAggregate *mObjects) : m_objects(mObjects) {
    m_cursor = -1;
}

void ConcreteIterator::first() {
    m_cursor = 0;
}

void ConcreteIterator::next() {
    if (hasNext()) {
        m_cursor++;
    }
}

bool ConcreteIterator::hasNext() {
    return m_cursor < (int)m_objects->size() - 1;
}

Object *ConcreteIterator::currentItem() {
    return m_objects->getObject(m_cursor);
}

uint32_t ConcreteAggregate::size() {
    return m_objects.size();
}

Object *ConcreteAggregate::getObject(int index) {
    return m_objects[index];
}

void ConcreteAggregate::pushBack(Object *obj) {
    m_objects.push_back(obj);
}

ConcreteAggregate::~ConcreteAggregate() {
    for (auto &it : m_objects) {
        delete it;
    }
    m_objects.clear();
}

main.cpp

cpp 复制代码
#include <iostream>
#include <mutex>
#include "myclass.h"

int main() {
    ConcreteAggregate *aggregate = new ConcreteAggregate();
    aggregate->pushBack(new Object(1));
    aggregate->pushBack(new Object(2));
    aggregate->pushBack(new Object(3));
    aggregate->pushBack(new Object(4));
    Iterator *it = aggregate->createIterator();
    do {
        it->next();
        std::cout << it->currentItem()->getId() << std::endl;
    } while (it->hasNext());
    delete it;
    delete aggregate;
    return 0;
}

总结

优点

  1. 支持以不同的方式遍历一个聚合对象,在同一个聚合对象上可以定义多种遍历方式。在迭代器模式中只需要用一个不同的迭代器来替换原有迭代器即可改变遍历算法,也可以自己定义迭代器的子类以支持新的遍历方式。

  2. 迭代器简化了聚合类。由于引入了迭代器,在原有的聚合对象中不需要再自行提供数据遍历等方法,这样可以简化聚合类的设计。

  3. 在迭代器模式中,由于引入了抽象层,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足开闭原则的要求。

缺点

  1. 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。

  2. 抽象迭代器的设计难度较大,需要充分考虑到系统将来的扩展。

适用场景

  1. 访问一个聚合对象的内容而无须暴露它的内部表示。将聚合对象的访问与内部数据的存储分离,使得访问聚合对象时无须了解其内部实现细节。

  2. 需要为一个聚合对象提供多种遍历方式。

  3. 为遍历不同的聚合结构提供一个统一的接口,在该接口的实现类中为不同的聚合结构提供不同的遍历方式,而客户端可以一致性地操作该接口。

练习

myclass.h

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H

#include <iostream>
#include <unordered_map>
#include <atomic>
#include <vector>
#include <memory>
#include <list>

class Object {
public:
    Object(int id);
    int getId();
private:
    int m_id;
};

class Iterator {
public:
    virtual void first() = 0;
    virtual void next() = 0;
    virtual bool hasNext() = 0;
    virtual void currentItems(std::vector<Object *> &items) = 0;
};

class Aggregate {
public:
    virtual Iterator *createIterator(uint32_t num) = 0;
};

class ConcreteAggregate : public Aggregate {
public:
    ~ConcreteAggregate();
    Iterator *createIterator(uint32_t num) override;
    uint32_t size();
    Object *getObject(int index);
    void pushBack(Object *obj);
private:
    std::vector<Object *> m_objects;
};

class ConcreteIterator : public Iterator {
public:
    ConcreteIterator(ConcreteAggregate *mObjects, uint32_t num);

    void first() override;

    void next() override;

    bool hasNext() override;

    void currentItems(std::vector<Object *> &items) override;

private:
    ConcreteAggregate *m_objects;
    int m_cursor;
    uint32_t m_num;
};



#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#include "myclass.h"
#include <thread>
#include <unistd.h>
#include <sstream>

Object::Object(int id) {
    m_id = id;
}

int Object::getId() {
    return m_id;
}

Iterator *ConcreteAggregate::createIterator(uint32_t num) {
    return new ConcreteIterator(this, num);
}

ConcreteIterator::ConcreteIterator(ConcreteAggregate *mObjects, uint32_t num) : m_objects(mObjects), m_num(num) {
    m_cursor = -m_num;
}

void ConcreteIterator::first() {
    m_cursor = 0;
}

void ConcreteIterator::next() {
    if (hasNext()) {
        m_cursor += m_num;
    }
}

bool ConcreteIterator::hasNext() {
    return m_cursor < (int)(m_objects->size() - m_num);
}

void ConcreteIterator::currentItems(std::vector<Object *> &items) {
    for (uint32_t i = m_cursor; i < m_cursor + m_num && i < m_objects->size(); ++i) {
        items.push_back(m_objects->getObject(i));
    }
}

uint32_t ConcreteAggregate::size() {
    return m_objects.size();
}

Object *ConcreteAggregate::getObject(int index) {
    return m_objects[index];
}

void ConcreteAggregate::pushBack(Object *obj) {
    m_objects.push_back(obj);
}

ConcreteAggregate::~ConcreteAggregate() {
    for (auto &it : m_objects) {
        delete it;
    }
    m_objects.clear();
}

main.cpp

cpp 复制代码
#include <iostream>
#include <mutex>
#include "myclass.h"

int main() {
    ConcreteAggregate *aggregate = new ConcreteAggregate();
    aggregate->pushBack(new Object(1));
    aggregate->pushBack(new Object(2));
    aggregate->pushBack(new Object(3));
    aggregate->pushBack(new Object(4));
    Iterator *it = aggregate->createIterator(2);
    std::vector<Object *> items;
    int page = 0;
    do {
        it->next();
        it->currentItems(items);
        std::cout << "第" << page++ << "页:" << std::endl;
        for (auto &i : items) {
            std::cout << i->getId() << std::endl;
        }
        items.clear();
    } while (it->hasNext());
    delete it;
    delete aggregate;
    return 0;
}
相关推荐
EQ-雪梨蛋花汤21 分钟前
【Unity笔记】Unity Animation组件使用详解:Play方法重载与动画播放控制
笔记·unity·游戏引擎
scdifsn22 分钟前
动手学深度学习13.3. 目标检测和边界框-笔记&练习(PyTorch)
笔记·深度学习·目标检测·目标识别·标注边界框
不会编程的小江江42 分钟前
【设计模式】UML类图与工厂模式
c++·设计模式
霸王蟹1 小时前
前端项目Excel数据导出同时出现中英文表头错乱情况解决方案。
笔记·学习·typescript·excel·vue3·react·vite
LuH11241 小时前
【论文阅读笔记】ICLR 2025 | 解析Ref-Gaussian如何实现高质量可交互反射渲染
论文阅读·笔记·论文笔记
lpfasd1232 小时前
备忘录模式(Memento Pattern)
java·设计模式·备忘录模式
AgilityBaby2 小时前
Untiy打包安卓踩坑
android·笔记·学习·unity·游戏引擎
lpfasd1232 小时前
模板方法模式(Template Method Pattern)
java·开发语言·设计模式·模板方法模式
lpfasd1235 小时前
状态模式(State Pattern)
java·设计模式·状态模式
Dream耀6 小时前
解锁JavaScript函数式编程的核心技能
前端·javascript·设计模式