【第22節】C++設計模式(行為模式)-Iterator(迭代器)模式

一、問題背景

????????Iterator 模式是設計模式中最為常見和實用的模式之一。它的核心思想是將對聚合對象的遍歷操作封裝到一個獨立的類中,從而避免暴露聚合對象的內部表示。通過 Iterator 模式,我們可以實現對聚合對象的統一遍歷接口,而不需要關心聚合對象的具體實現細節。

????????在實際開發中,Iterator 模式的應用非常廣泛。例如,在實現 Composite 模式、Flyweight 模式、Observer 模式時,我們經常會使用 STL 提供的 Iterator 來遍歷 `Vector` 或 `List` 等數據結構。Iterator 模式不僅簡化了遍歷操作,還提高了代碼的可維護性和可擴展性。

二、模式選擇

????????Iterator 模式的典型結構圖如下:

在 Iterator 模式中,主要包含以下幾個角色:

(1)Aggregate(聚合):定義創建 Iterator 對象的接口。
(2)ConcreteAggregate(具體聚合):實現 Aggregate 接口,返回一個具體的 Iterator 實例。
(3)Iterator(迭代器):定義遍歷聚合對象的接口。
(4)ConcreteIterator(具體迭代器):實現 Iterator 接口,負責遍歷具體的聚合對象。

????????通過這種設計,Iterator 模式將聚合對象的遍歷邏輯與其內部實現分離,使得聚合對象可以獨立于遍歷邏輯進行修改。

三、代碼實現

????????下面我們將通過一個完整的 C++ 代碼示例來展示如何實現 Iterator 模式。為了方便初學者的學習和參考,代碼將包含詳細的注釋。

代碼片段 1:Aggregate.h

// Aggregate.h
#ifndef _AGGREGATE_H_
#define _AGGREGATE_H_class Iterator;
typedef int Object;  // 定義聚合對象中存儲的數據類型// Aggregate 類:定義創建 Iterator 對象的接口
class Aggregate {
public:virtual ~Aggregate();virtual Iterator* CreateIterator() = 0;  // 創建迭代器virtual Object GetItem(int idx) = 0;     // 獲取指定位置的元素virtual int GetSize() = 0;               // 獲取聚合對象的大小
protected:Aggregate();
private:
};// ConcreteAggregate 類:具體聚合類,實現 Aggregate 接口
class ConcreteAggregate : public Aggregate {
public:enum { SIZE = 3 };  // 定義聚合對象的大小ConcreteAggregate();~ConcreteAggregate();Iterator* CreateIterator();  // 創建迭代器Object GetItem(int idx);     // 獲取指定位置的元素int GetSize();               // 獲取聚合對象的大小
protected:
private:Object _objs[SIZE];  // 聚合對象中存儲的數據
};#endif //~_AGGREGATE_H_

代碼片段 2:Aggregate.cpp

// Aggregate.cpp
#include "Aggregate.h"
#include "Iterator.h"
#include <iostream>
using namespace std;// Aggregate 類的實現
Aggregate::Aggregate() {// 構造函數
}Aggregate::~Aggregate() {// 析構函數
}// ConcreteAggregate 類的實現
ConcreteAggregate::ConcreteAggregate() {// 初始化聚合對象中的數據for (int i = 0; i < SIZE; i++) {_objs[i] = i;}
}ConcreteAggregate::~ConcreteAggregate() {// 析構函數
}Iterator* ConcreteAggregate::CreateIterator() {// 創建具體的迭代器對象return new ConcreteIterator(this);
}Object ConcreteAggregate::GetItem(int idx) {// 獲取指定位置的元素if (idx < this->GetSize()) {return _objs[idx];} else {return -1;  // 如果索引越界,返回 -1}
}int ConcreteAggregate::GetSize() {// 獲取聚合對象的大小return SIZE;
}

代碼片段 3:Iterator.h

// Iterator.h
#ifndef _ITERATOR_H_
#define _ITERATOR_H_class Aggregate;
typedef int Object;  // 定義聚合對象中存儲的數據類型// Iterator 類:定義遍歷聚合對象的接口
class Iterator {
public:virtual ~Iterator();virtual void First() = 0;          // 將迭代器指向第一個元素virtual void Next() = 0;           // 將迭代器指向下一個元素virtual bool IsDone() = 0;         // 判斷是否遍歷結束virtual Object CurrentItem() = 0;  // 獲取當前元素
protected:Iterator();
private:
};// ConcreteIterator 類:具體迭代器類,實現 Iterator 接口
class ConcreteIterator : public Iterator {
public:ConcreteIterator(Aggregate* ag, int idx = 0);  // 構造函數~ConcreteIterator();void First();          // 將迭代器指向第一個元素void Next();           // 將迭代器指向下一個元素bool IsDone();         // 判斷是否遍歷結束Object CurrentItem();  // 獲取當前元素
protected:
private:Aggregate* _ag;  // 聚合對象int _idx;        // 當前索引
};#endif //~_ITERATOR_H_

代碼片段 4:Iterator.cpp

// Iterator.cpp
#include "Iterator.h"
#include "Aggregate.h"
#include <iostream>
using namespace std;// Iterator 類的實現
Iterator::Iterator() {// 構造函數
}Iterator::~Iterator() {// 析構函數
}// ConcreteIterator 類的實現
ConcreteIterator::ConcreteIterator(Aggregate* ag, int idx) {this->_ag = ag;  // 初始化聚合對象this->_idx = idx;  // 初始化當前索引
}ConcreteIterator::~ConcreteIterator() {// 析構函數
}Object ConcreteIterator::CurrentItem() {// 獲取當前元素return _ag->GetItem(_idx);
}void ConcreteIterator::First() {// 將迭代器指向第一個元素_idx = 0;
}void ConcreteIterator::Next() {// 將迭代器指向下一個元素if (_idx < _ag->GetSize()) {_idx++;}
}bool ConcreteIterator::IsDone() {// 判斷是否遍歷結束return (_idx == _ag->GetSize());
}

代碼片段 5:main.cpp

// main.cpp
#include "Iterator.h"
#include "Aggregate.h"
#include <iostream>
using namespace std;int main(int argc, char* argv[]) {// 創建聚合對象Aggregate* ag = new ConcreteAggregate();// 創建迭代器對象Iterator* it = ag->CreateIterator();// 遍歷聚合對象for (; !(it->IsDone()); it->Next()) {cout << it->CurrentItem() << endl;}// 釋放內存delete it;delete ag;return 0;
}

代碼說明

(1)Aggregate 類:定義了創建 Iterator 對象的接口,并提供了獲取聚合對象大小和元素的方法。
(2)ConcreteAggregate 類:實現了 Aggregate 接口,內部維護了一個固定大小的數組。
(3)Iterator 類:定義了遍歷聚合對象的接口,包括移動到第一個元素、移動到下一個元素、判斷是否遍歷結束以及獲取當前元素的方法。
(4)ConcreteIterator 類:實現了 Iterator 接口,負責遍歷 ConcreteAggregate 對象。

?

四、總結討論

????????Iterator 模式的應用非常廣泛,尤其是在需要對聚合對象進行遍歷時。通過將遍歷邏輯封裝到獨立的 Iterator 類中,我們可以實現以下優點:

(1)簡化遍歷操作:客戶端代碼只需要調用 Iterator 的接口即可完成遍歷,無需關心聚合對象的內部實現。
(2)提高代碼復用性:可以為不同的聚合對象提供統一的遍歷接口。
(3)增強靈活性:可以在不修改聚合對象的情況下,擴展或修改遍歷邏輯。

????????在實際開發中,STL 提供的 Iterator 就是一個典型的應用。例如,我們可以使用 `std::vector<int>::iterator` 來遍歷 `std::vector<int>`,而無需關心 `std::vector` 的內部實現。

????????Iterator 模式通過將對聚合對象的遍歷操作封裝到獨立的類中,實現了遍歷邏輯與聚合對象的解耦。這種設計模式不僅簡化了代碼結構,還提高了代碼的可維護性和可擴展性。在實際開發中,Iterator 模式是處理聚合對象遍歷問題的首選方案。

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/73011.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/73011.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/73011.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

02C#基本結構篇(D4_注釋-訪問修飾符-標識符-關鍵字-運算符-流程控制語句)

目錄 一、注釋 1. 單行注釋 2. 多行注釋 3. XML文檔注釋 4. 使用建議和最佳實踐&#xff1a; 二、訪問修飾符 1. public 2. private 3. protected 4. internal 5. protected internal 或 protected and internal 6. private protected 或 private and protected 7.…

【CXX】6.2 str — rust::Str

Rust::Str 公共 API // rust/cxx.hclass Str final { public:Str() noexcept;Str(const Str &) noexcept;Str(const String &) noexcept;// 如果輸入不是 UTF-8&#xff0c;拋出 std::invalid_argument 異常。Str(const std::string &);Str(const char *);Str(con…

基于windows的MySQL安裝(2025最新,小白可用)

目錄 一&#xff0c;下載官網地址&#xff08;及版本選擇&#xff09;&#xff1a; 二&#xff0c;以安裝程序的方式安裝MySQL 1&#xff0c;安裝過程 2&#xff0c;用客戶端使用MySQL 3&#xff0c;配置環境變量在windows命令行界面使用mysql 下次開機后手動啟用服務 三…

Jenkins實現自動化構建與部署:上手攻略

一、持續集成與Jenkins核心價值 1.1 為什么需要自動化構建&#xff1f; 在現代化軟件開發中&#xff0c;團隊每日面臨以下挑戰&#xff1a; 高頻代碼提交&#xff1a;平均每個開發者每天提交5-10次代碼。多環境部署&#xff1a;開發、測試、預發布、生產環境需頻繁同步。復雜…

4個 Vue 路由實現的過程

大家好&#xff0c;我是大澈&#xff01;一個喜歡結交朋友、喜歡編程技術和科技前沿的老程序員&#x1f468;&#x1f3fb;?&#x1f4bb;&#xff0c;關注我&#xff0c;科技未來或許我能幫到你&#xff01; Vue 路由相信朋友們用的都很熟了&#xff0c;但是你知道 Vue 路由…

數學之快速冪-數的冪次

題目描述 給定三個正整數 N,M,P&#xff0c;求 輸入描述 第 1 行為一個整數 T&#xff0c;表示測試數據數量。 接下來的 T 行每行包含三個正整數 N,M,P。 輸出描述 輸出共 T 行&#xff0c;每行包含一個整數&#xff0c;表示答案。 輸入輸出樣例 示例 1 輸入 3 2 3 7 4…

【JavaEE】多線程進階(2)

【JavaEE】多線程進階&#xff08;2&#xff09; 一、JUC(java.util.concurrent) 的常?類1.1 Callable 接?1.2 ReentrantLock1.3 原子類原子類的特性&#xff1a;常見原子類&#xff1a;原子類的實例&#xff1a; 1.4 線程池1.5 信號量 Semaphore代碼實例 1.6 CountDownLatch…

[漏洞篇]XSS漏洞詳解

[漏洞篇]XSS漏洞 一、 介紹 概念 XSS&#xff1a;通過JS達到攻擊效果 XSS全稱跨站腳本(Cross Site Scripting)&#xff0c;為避免與層疊樣式表(Cascading Style Sheets, CSS)的縮寫混淆&#xff0c;故縮寫為XSS。這是一種將任意 Javascript 代碼插入到其他Web用戶頁面里執行以…

越早越好!8 個反直覺的金錢真相|金錢心理學

很多人都追求財富自由&#xff0c;但成功的人少之又少。 這可能是因為&#xff0c;人們往往忽略了一些金錢的真相和常識。 01 金錢常識 & 真相 為了構建健康的金錢觀&#xff0c;我讀了一本有點反直覺&#xff0c;有點像雞湯&#xff0c;但都是財富真相的書。 來自 Morg…

Spring Boot/Spring Cloud 整合 ELK(Elasticsearch、Logstash、Kibana)詳細避坑指南

我們在開發中經常會寫日志&#xff0c;所以需要有個日志可視化界面管理&#xff0c;使用ELK可以實現高效集中化的日志管理與分析&#xff0c;提升性能穩定性&#xff0c;滿足安全合規要求&#xff0c;支持開發運維工作。 下述是我在搭建ELK時遇到的許許多多的坑&#xff0c;希望…

AI編程: 一個案例對比CPU和GPU在深度學習方面的性能差異

背景 字節跳動正式發布中國首個AI原生集成開發環境工具&#xff08;AI IDE&#xff09;——AI編程工具Trae國內版。 該工具模型搭載doubao-1.5-pro&#xff0c;支持切換滿血版DeepSeek R1&V3&#xff0c; 可以幫助各階段開發者與AI流暢協作&#xff0c;更快、更高質量地完…

手機屏幕摔不顯示了,如何用其他屏幕臨時顯示,用來導出資料或者清理手機

首先準備一個拓展塢 然后 插入一個外接的U盤 插入鼠標 插入有數字小鍵盤區的鍵盤 然后準備一根高清線&#xff0c;一端鏈接電腦顯示器,一端插入拓展塢 把拓展塢的連接線&#xff0c;插入手機充電口&#xff08;可能會需要轉接頭&#xff09; 然后確保手機開機 按下鍵盤…

探索鏈表的奧秘:C語言中的查找操作與鏈表打印

目錄 鏈表的基本結構 頭插法 打印鏈表 按位置查找 按值查找 主函數 查找操作 示例運行 輸出示例 總結 在數據結構的學習中&#xff0c;鏈表是一種非常重要的線性結構。它的動態特性使得在插入和刪除操作時比數組更為高效。今天&#xff0c;我們將繼續探討鏈表的操作&…

第八屆藍橋杯單片機省賽

什么&#xff1f;你把最近幾屆省賽真題做完已經無題可做了&#xff0c;那不妨來看看老古董第八屆省賽的題目吧&#xff01; 附件&#xff1a;第八屆藍橋杯單片機省賽 一、數碼管 1.頁面流轉 以上的頁面流轉功能可以用下圖總結&#xff1a; #mermaid-svg-38fdQpdydbMy5CyP {fo…

win10電腦鼠標速度突然變的很慢?

電腦鼠標突然變很慢&#xff0c;殺毒檢測后沒問題&#xff0c;鼠標設置也沒變&#xff0c;最后發現可能是誤觸鼠標的“DPI”調節鍵。 DPI調節鍵在鼠標滾輪下方&#xff0c;再次點擊即可恢復正常鼠標速度。 如果有和-的按鍵&#xff0c;速度變快&#xff0c;-速度變慢。 圖源&…

1-002:MySQL InnoDB引擎中的聚簇索引和非聚簇索引有什么區別?

在 MySQL InnoDB 存儲引擎 中&#xff0c;索引主要分為 聚簇索引&#xff08;Clustered Index&#xff09; 和 非聚簇索引&#xff08;Secondary Index&#xff09;。它們的主要區別如下&#xff1a; 1. 聚簇索引&#xff08;Clustered Index&#xff09; 定義 聚簇索引是表數…

【解決哈希沖突】

哈希沖突 如果兩個不同的 key 通過哈希函數得到了相同的索引&#xff0c;這種情況就叫做「哈希沖突」。 哈希沖突不可能避免&#xff0c;只能在算法層面妥善處理出現哈希沖突的情況。 哈希沖突是一定會出現的&#xff0c;因為這個 hash 函數相當于是把一個無窮大的空間映射到…

文件操作詳解(萬字長文)

C語言文件操作 一、為什么使用文件&#xff1f;二、文件分類三、文件的打開和關閉四、文件的順序讀寫4.1fputc4.2fgetc4.3fputs4.4fgets4.5 fprintf4.6 fscanf4.7 fwrite4.8 fread 五、文件的隨機讀寫5.1 fseek5.2 ftell和rewind六、文件讀取結束的判定七、文件緩沖區 一、為什…

基于 JDBC 的后端與 MySQL 數據庫交互 javaweb

一、了解JDBC 二、添加MySQL的JDBC驅動包 三、使用JDBC連接數據庫應用&#x1f517; 3.1創建一個包 3.2 查找實例 3.3 修改添加刪除實例 四、封裝 &#x1f4e6; DBConnection.java MysqlUtil.java 測試使用一下 測試1 測試2 在后端開發中&#xff0c;與數據庫進行交…

貪心算法--

1.檸檬水找零 link:860. 檸檬水找零 - 力扣&#xff08;LeetCode&#xff09; code class Solution { public:bool lemonadeChange(vector<int>& bills) {// 貪心算法&#xff0c; 優先花出大面額bill&#xff0c; 盡可能保護小面額billint five 0, ten 0;// 不…