【声明】本题目来源于卡码网(https://kamacoder.com/)
【提示:如果不想看文字介绍,可以直接跳转到C++编码部分】
? ? ? ? --什么是迭代器模式(第19种设计模式)
????????迭代器模式是?种行为设计模式,是?种使?频率?常?的设计模式,在各个语?中都有应用,其主要?的是提供?种统?的?式来访问?个聚合对象中的各个元素,而不需要暴露该对象的内部表示。通过迭代器,客户端可以顺序访问聚合对象的元素,而无需了解底层数据结构。
迭代器模式应??泛,但是?多数语?都已经内置了迭代器接?,不需要??实现。
????????迭代器模式包括以下?个重要角色
????????下面以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());
}
}
}
????????迭代器模式是?种通用的设计模式,其封装性强,简化了客户端代码,客户端不需要知道集合的内部结构,只需要关心迭代器和迭代接口就可以完成元素的访问。但是引?迭代器模式会增加额外的类,每增加?个集合类,都需要增加该集合对应的迭代器,这也会使得代码结构变得更加复杂。
????????许多编程语?和框架都使用了这个模式提供?致的遍历和访问集合元素的机制。下?是几种常见语?迭代器模式的实现。
????????集合类(如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());
}
????????使用迭代器和?成器来实现迭代模式, iter() 和next() 函数可以?于创建和访问迭代器。
elements = ["Element 1", "Element 2", "Element 3"]
iterator = iter(elements)
while True:
try:
element = next(iterator)
print(element)
except StopIteration:
break
????????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;
}
????????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);
}
????????小明是一位老师,在进行班级点名时,希望有一个学生名单系统,请你实现迭代器模式提供一个迭代器使得可以按顺序遍历学生列表。
????????第一行是一个整数 N (1 <= N <= 100), 表示学生的数量。接下来的 N 行,每行包含一个学生的信息,格式为 姓名 学号;
????????输出班级点名的结果,即按顺序遍历学生列表,输出学生的姓名和学号;
/**
* @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.