C++设计模式之迭代器模式

发布时间:2024年01月23日

【声明】本题目来源于卡码网(https://kamacoder.com/

【提示:如果不想看文字介绍,可以直接跳转到C++编码部分


设计模式大纲】


【简介】

? ? ? ? --什么是迭代器模式(第19种设计模式)

????????迭代器模式是?种行为设计模式,是?种使?频率?常?的设计模式,在各个语?中都有应用,其主要?的是提供?种统?的?式来访问?个聚合对象中的各个元素,而不需要暴露该对象的内部表示。通过迭代器,客户端可以顺序访问聚合对象的元素,而无需了解底层数据结构。

迭代器模式应??泛,但是?多数语?都已经内置了迭代器接?,不需要??实现。


【基本结构】

????????迭代器模式包括以下?个重要角色

  • 迭代器接口Iterator :定义访问和遍历元素的接?, 通常会包括hasNext() ?法?于检查是否还有下?个元素,以及next() ?法?于获取下?个元素。有的还会实现获取第?个元素以及获取当前元素的?法。
  • 具体迭代器ConcreateIterator :实现迭代器接?,实现遍历逻辑对聚合对象进?遍历。
  • 抽象聚合类:定义了创建迭代器的接?,包括?个createIterator ?法?于创建?个迭代器对象。
  • 具体聚合类:实现在抽象聚合类中声明的createIterator() ?法,返回?个与具体聚合对应的具体迭代器


【简易实现--Java】

????????下面以Java代码作以说明:

1. 定义迭代器接口:通常会有检查是否还有下?个元素以及获取下?个元素的?法。

// 迭代器接?
public interface Iterator{
    // 检查是否还会有下?个元素
    boolean hasNext();
    // 获取下?个元素
    Object next();
}

2.?定义具体迭代器:实现迭代器接口,遍历集合。

public class ConcreteIterator implements Iterator {
    private int index;
    private List<Object> elements;
    // 构造函数初始化迭代器
    public ConcreteIterator(List<Object> elements) {
        this.elements = elements;
        this.index = 0;
    }
    @Override
    public boolean hasNext() {
        return index < elements.size();
    }
    @Override
    public Object next() {
        if (hasNext()) {
            return elements.get(index++);
        }
        return null;
    }
}

3. 定义聚合接口:通常包括createIterator() ?法,?于创建迭代器

public interface Iterable {
    Iterator createIterator();
}

4. 实现具体聚合:创建具体的迭代器

// 具体聚合
public class ConcreteIterable implements Iterable {
    private List<Object> elements;
    // 构造函数初始化可迭代对象
    public ConcreteIterable(List<Object> elements) {
        this.elements = elements;
    }
    @Override
    public Iterator createIterator() {
        return new ConcreteIterator(elements);
    }
}

5. 客户端使用

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file TemplateMethodMode.hpp
* @brief 模板方法模式
* @autor 写代码的小恐龙er
* @date 2024/01/23
*/
import java.util.ArrayList;
import java.util.List;
public class IteratorPatternExample {
    public static void main(String[] args) {
        List<Object> elements = new ArrayList<>();
        elements.add("Element 1");
        elements.add("Element 2");
        elements.add("Element 3");

        Iterable iterable = new ConcreteIterable(elements);
        Iterator iterator = iterable.createIterator();

        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

【使用场景】

????????迭代器模式是?种通用的设计模式,其封装性强,简化了客户端代码,客户端不需要知道集合的内部结构,只需要关心迭代器和迭代接口就可以完成元素的访问。但是引?迭代器模式会增加额外的类,每增加?个集合类,都需要增加该集合对应的迭代器,这也会使得代码结构变得更加复杂。
????????许多编程语?和框架都使用了这个模式提供?致的遍历和访问集合元素的机制。下?是几种常见语?迭代器模式的实现。

1. Java语言

????????集合类(如ArrayList、LinkedList), 通过Iterator 接?,可以遍历集合中的元素。

List<String> list = new ArrayList<>();
list.add("Item 1");
list.add("Item 2");
list.add("Item 3");

Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

2. Python语言

????????使用迭代器和?成器来实现迭代模式, iter() 和next() 函数可以?于创建和访问迭代器。

elements = ["Element 1", "Element 2", "Element 3"]
iterator = iter(elements)

while True:
    try:
        element = next(iterator)
        print(element)
    except StopIteration:
        break

3. C++语言

????????C++中的STL提供了迭代器的?持, begin() 和end() 函数可以?于获取容器的起始和结束迭代器。

#include <iostream>
#include <vector>
int main() {
    std::vector<std::string> elements = {"Element 1", "Element 2", "Element 3"};
    for (auto it = elements.begin(); it != elements.end(); ++it) {
        std::cout << *it << std::endl;
    }
    return 0;
}

4. JavaScript语言

????????ES6中新增了迭代器协议,使得遍历和访问集合元素变得更加方便。

// 可迭代对象实现可迭代协议
class IterableObject {
    constructor() {
        this.elements = [];
    }
    addElement(element) {
        this.elements.push(element);
    }
    [Symbol.iterator]() {
        let index = 0;
        // 迭代器对象实现迭代器协议
        return {
            next: () => {
                if (index < this.elements.length) {
                    return { value: this.elements[index++], done: false };
                } else {
                    return { done: true };
                }
            }
        };
    }
}
// 使?迭代器遍历可迭代对象
const iterableObject = new IterableObject();
iterableObject.addElement("Element 1");
iterableObject.addElement("Element 2");
iterableObject.addElement("Element 3");

for (const element of iterableObject) {
    console.log(element);
}

【编码部分】

1. 题目描述

????????小明是一位老师,在进行班级点名时,希望有一个学生名单系统,请你实现迭代器模式提供一个迭代器使得可以按顺序遍历学生列表。

2. 输入描述

????????第一行是一个整数 N (1 <= N <= 100), 表示学生的数量。接下来的 N 行,每行包含一个学生的信息,格式为 姓名 学号;

3. 输出描述

????????输出班级点名的结果,即按顺序遍历学生列表,输出学生的姓名和学号;

4. C++编程实例

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file IteratorMode.hpp
* @brief 迭代器模式
* @autor 写代码的小恐龙er
* @date 2024/01/23
*/

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

using namespace std;

// 前置声明

// 聚合元素类 -- 学生
class Student;

// 迭代器接口 -- 提前声明模板
template<class T>
class Iterator;

// 具体迭代器 -- 学生遍历 迭代类
class ConcreteStudentIterator;

// 聚合接口 -- 学生全体类
class StudentCollection;

// 具体的聚合类 -- 创建全体学生
class ConcreteStudentCollection;

// 类的实现

// 聚合元素类 -- 学生
class Student{
// 成员数据
private:
    string _name;
    int _idNumber;
// 成员函数
public:
    // 构造函数
    Student(string name, int id){
        this->_name = name;
        this->_idNumber = id;
    }
    // 获取成员数据
    string GetName(){
        return this->_name;
    }
    int GetIdNumber(){
        return this->_idNumber;
    }
};

// 迭代器接口
// 类模板 
template<class T>
class Iterator{
// 迭代器接口
public:
    // 接口函数声明为 纯虚函数
    virtual bool isHavNext() = 0;
    virtual T* Next() = 0;
};

// 具体迭代器 -- 学生遍历 迭代类
class ConcreteStudentIterator : public Iterator<Student>
{
// 成员数据 
private:
    std::vector<Student *> _studentsVec;
    int _currentIndex = 0;
// 成员函数
public:
    // 构造函数
    ConcreteStudentIterator(std::vector<Student *> studentsVec){
        this->_studentsVec = studentsVec;
    }
    // 重载接口函数
    bool isHavNext() override{
        return _currentIndex < _studentsVec.size();
    }
    Student*  Next() override {
        if(isHavNext()){
            return _studentsVec[_currentIndex++];
        }
        return nullptr;
    }
};

// 聚合接口 -- 学生全体类
class StudentCollection
{
// 迭代器对象 接口函数
public:
    virtual Iterator<Student> * iterator() = 0;
};

// 具体的聚合类 -- 创建全体学生
class ConcreteStudentCollection : public StudentCollection
{
// 成员数据 
private:
    std::vector<Student *> _students;
// 成员函数
public:
    // 构造函数
    ConcreteStudentCollection(){}
    ConcreteStudentCollection(std::vector<Student *> students){
        this->_students = students;
    }
    // 添加学生对象
    void AddStudent(Student * student){
        _students.push_back(student);
    }
    // 迭代器接口函数重载  返回值为迭代器基类的指针 模板类型为Student
    Iterator<Student> * iterator() override{
        // 涉及到 隐式地 向上类型转换 派生类 转换为 基类 线程安全
        return new ConcreteStudentIterator(_students);
    }
};

int main()
{
    // 学生数量
    int studentNum = 0;
    // 输入
    std::cin >> studentNum;
    // 创建学生类
    Student *student = nullptr;
    // 创建具体可迭代对象
    ConcreteStudentCollection *concreteStudentCollection = new ConcreteStudentCollection();
    // 学生遍历
    for(int i = 0; i < studentNum; i++){
        // 学生姓名和学号
        string name = "";
        int numberId = 0;
        // 输入
        std::cin >> name >> numberId;
        // 构造学生类
        student = new Student(name, numberId);
        // 将学生放入 学生收集器类 中 
        concreteStudentCollection->AddStudent(student);
    }
    
    // 遍历结束后 再来通过迭代器模式 进行 信息打印
    // 调用具体聚合类中的 迭代器生成 接口!
    Iterator<Student> *iterator = concreteStudentCollection->iterator();
    while(iterator->isHavNext()){
        // 从迭代器中的学生集合获取学生类
        student = iterator->Next();
        // 打印学生信息
        if(student != nullptr){
            // 由于学生类中的成员数据为私有类型 记得调用接口函数去获取成员数据
            // 输出长度不足补0; 固定输出长度为3;
            std::cout << student->GetName() << " " << setw(3) << setfill('0') << student->GetIdNumber() << endl;
        }
        else std::cout << "Invalid input" << endl;
        
    }
    
    // 记得析构!!!
    // 记得析构!!!
    // 记得析构!!!
    if(student != nullptr){
        delete student;
        student = nullptr;
    }
    delete concreteStudentCollection;
    concreteStudentCollection = nullptr;
    
    return 0;
}




......

To be continued.

文章来源:https://blog.csdn.net/K1_uestc/article/details/135772598
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。