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

介绍

迭代器模式提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示,其别名为游标(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;
}
相关推荐
孤寂大仙v2 分钟前
【Linux笔记】理解文件系统(上)
linux·运维·笔记
ianozo4 分钟前
数据结构--【栈与队列】笔记
数据结构·笔记
极客BIM工作室1 小时前
机器学校的考试风波:误差分析、过拟合和欠拟合
笔记·机器学习
flashier1 小时前
C语言 进阶指针学习笔记
c语言·笔记·学习
大白的编程日记.2 小时前
【Linux学习笔记】Linux基本指令分析和权限的概念
linux·笔记·学习
螺旋式上升abc2 小时前
GO语言学习笔记
笔记·学习·golang
Moonnnn.3 小时前
51单片机——汇编工程建立、仿真、调试全过程
汇编·笔记·嵌入式硬件·学习·51单片机
画个逗号给明天"3 小时前
TinyWebServer项目笔记——02 半同步半反应堆线程池
笔记
不会聊天真君6473 小时前
HTML5(Web前端开发笔记第一期)
笔记·html5
!!!5253 小时前
Sentinel 笔记
笔记·sentinel