• 20 C++设计模式之迭代器(Iterator)模式


    迭代器(Iterator)模式定义

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

    迭代器(Iterator)模式优缺点

    优点
    • 单一职责原则。通过将体积庞大的遍历算法代码抽取为独立的类,你可对客户端代码和集合进行整理。
    • 开闭原则。你可实现新型的集合和迭代器并将其传递给现有代码,无需修改现有代码。
    • 你可以并行遍历同一集合,因为每个迭代器对象都包含其自身的遍历状态。
    • 相似的,你可以暂停遍历并在需要时继续。
    缺点
    • 如果你的程序只与简单的集合进行交互,应用该模式可能会矫枉过正。
    • 对于某些特殊集合,使用迭代器可能比直接遍历的效率低

    迭代器(Iterator)模式构成与实现

    构成
    • 迭代器(Iterator):接口类,声明了遍历集合所需的操作(获取下一个元素、获取当前位置和重新开始迭代等)。
    • 具体迭代器(Concrete Iterators) :实现遍历集合的一种特定算法。迭代器对象必须跟踪自身遍历的进度,这使得多个迭代器可以相互独立地遍历同一集合。
    • 集合(Collection):接口类,声明一个或多个方法来获取与集合兼容的迭代器。请注意,返回方法的类型必须被声明为迭代器接口,因此具体集合可以返回各种不同种类的迭代器。
    • 具体集合(Concrete Collections) :会在客户端请求迭代器时返回一个特定的具体迭代器类实体。你可能会琢磨,剩下的集合代码在什么地方呢? 不用担心, 它也会在同一个类中。只是这些细节对于实际模式来说并不重要,所以我们将其省略了而已。
    • 客户端(Client):通过集合和迭代器的接口与两者进行交互。这样一来客户端无需与具体类进行耦合,允许同一客户端代码使用各种不同的集合和迭代器。客户端通常不会自行创建迭代器,而是会从集合中获取。但在特定情况下,客户端可以直接创建一个迭代器(例如当客户端需要自定义特殊迭代器时)。
    实例

    Iterator.h:

    #ifndef ITERATOR_H_
    #define ITERATOR_H_
    
    #include 
    
    // 抽象迭代器
    class TVIterator{
     public:
        virtual void setChannel(int i) = 0;
        virtual void next() = 0;
        virtual void previous() = 0;
        virtual bool isLast() = 0;
        virtual std::string currentChannel() = 0;
        virtual bool isFirst() = 0;
    };
    
    #endif  // ITERATOR_H_
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    ConcreteIterator.h:

    #ifndef CONCRETE_ITERATOR_H_
    #define CONCRETE_ITERATOR_H_
    
    #include 
    #include 
    #include "Iterator.h"
    
    // 具体迭代器
    class SkyworthIterator : public TVIterator{
     public:
        explicit SkyworthIterator(std::vector<std::string> &tvs) : tvs_(tvs) {}
    
        void next() override {
            if (current_index_ < tvs_.size()) {
                current_index_++;
            }
        }
    
        void previous() override {
            if (current_index_ > 0) {
                current_index_--;
            }
        }
    
        void setChannel(int i) override {
            current_index_ = i;
        }
    
        std::string currentChannel() override {
            return tvs_[current_index_];
        }
    
        bool isLast() override {
            return current_index_ == tvs_.size();
        }
    
        bool isFirst() override {
            return current_index_ == 0;
        }
    
     private:
        std::vector<std::string> &tvs_;
        int current_index_ = 0;
    };
    
    #endif  // CONCRETE_ITERATOR_H_
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    Collection.h:

    #ifndef COLLECTION_H_
    #define COLLECTION_H_
    
    #include 
    #include "Iterator.h"
    
    // 抽象集合
    class Television {
     public:
        virtual std::shared_ptr<TVIterator> createIterator() = 0;
    };
    
    #endif  // COLLECTION_H_
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    ConcreteCollection.h:

    #ifndef CONCRETE_COLLECTION_H_
    #define CONCRETE_COLLECTION_H_
    
    #include 
    #include 
    #include 
    #include "Collection.h"
    #include "ConcreteIterator.h"
    
    class SkyworthTelevision : public Television {
     public:
        std::shared_ptr<TVIterator> createIterator() {
            return std::make_shared<SkyworthIterator>(tvs_);
        }
    
        void addItem(std::string item) {
            tvs_.push_back(item);
        }
    
     private:
        std::vector<std::string> tvs_;
    };
    
    #endif  // CONCRETE_COLLECTION_H_
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    main.cpp

    #include 
    #include "ConcreteCollection.h"
    
    int main() {
    
        system("chcp 65001");
        SkyworthTelevision stv;
        stv.addItem("CCTV-1");
        stv.addItem("CCTV-2");
        stv.addItem("CCTV-3");
        stv.addItem("CCTV-4");
        stv.addItem("CCTV-5");
    
        auto iter = stv.createIterator();
        while (!iter->isLast()) {
            std::cout << iter->currentChannel() << std::endl;
            iter->next();
        }
        system("pause");
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    输出:

    Active code page: 65001
    CCTV-1
    CCTV-2
    CCTV-3
    CCTV-4
    CCTV-5
    Press any key to continue . . .
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    【线性存储结构总结】
    中国企业出海应尽早把握海外社交媒体运营红利-出海传播趋势的言灵视角
    长沙物业满意度调查找第三方|群狼调研(长沙物业竞争对手分析)
    mybatise-plus的id过长问题
    开源 Wiki 软件 wiki.js
    C++11新特性之十六:std::tie
    CSS读书笔记
    Cplex求解教程(基于OPL语言,可作为大规模运算输入参考)
    如何分分钟理解SVM(中文版)
    CAN电压测试(电工)
  • 原文地址:https://blog.csdn.net/qq_45531502/article/details/126419508