迭代器模式(Iterator Pattern)的核心是提供一种统一的方式遍历聚合对象(如数组、链表等)中的元素,而无需暴露聚合对象的内部结构 。在C语言中,可以通过迭代器结构体(封装遍历操作)+ 聚合结构体(提供获取迭代器的接口) 实现:迭代器负责跟踪当前位置并提供next、has_next等方法,聚合对象负责创建迭代器。
C语言实现迭代器模式的思路
- 迭代器接口(Iterator) :定义遍历元素的统一方法(
has_next判断是否有下一个元素,next获取下一个元素)。 - 具体迭代器(Concrete Iterator):实现迭代器接口,持有聚合对象的指针和当前遍历位置,负责实际遍历逻辑。
- 聚合接口(Aggregate) :定义创建迭代器的接口(
create_iterator)。 - 具体聚合(Concrete Aggregate):实现聚合接口,存储元素集合(如数组、链表),并创建对应的具体迭代器。
示例:遍历自定义链表(聚合)和数组(聚合)
实现对链表和数组两种聚合结构的统一遍历,客户端通过相同的迭代器接口操作,无需关心内部存储方式。
步骤1:定义迭代器接口
c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 前向声明聚合,避免循环依赖
typedef struct Aggregate Aggregate;
// 迭代器接口:定义遍历方法
typedef struct Iterator {
// 判断是否有下一个元素
bool (*has_next)(struct Iterator* self);
// 获取下一个元素(返回void*,支持任意类型)
void* (*next)(struct Iterator* self);
// 销毁迭代器
void (*destroy)(struct Iterator* self);
} Iterator;
步骤2:定义聚合接口
聚合接口负责创建对应迭代器。
c
// 聚合接口:定义创建迭代器的方法
typedef struct Aggregate {
// 创建迭代器
Iterator* (*create_iterator)(struct Aggregate* self);
// 销毁聚合
void (*destroy)(struct Aggregate* self);
} Aggregate;
步骤3:实现具体聚合与迭代器(链表)
3.1 链表聚合
c
// 链表节点
typedef struct ListNode {
void* data; // 节点数据
struct ListNode* next; // 下一个节点
} ListNode;
// 具体聚合:链表
typedef struct {
Aggregate aggregate; // 继承聚合接口
ListNode* head; // 链表头
ListNode* tail; // 链表尾
int size; // 元素数量
} LinkedList;
// 链表添加元素
void linked_list_add(LinkedList* list, void* data) {
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
if (!node) return;
node->data = data;
node->next = NULL;
if (list->tail) {
list->tail->next = node;
} else {
list->head = node; // 空链表时头节点为新节点
}
list->tail = node;
list->size++;
}
3.2 链表迭代器
c
// 具体迭代器:链表迭代器
typedef struct {
Iterator iterator; // 继承迭代器接口
LinkedList* list; // 关联的链表
ListNode* current; // 当前遍历位置
} ListIterator;
// 链表迭代器:判断是否有下一个元素
static bool list_has_next(Iterator* self) {
ListIterator* iter = (ListIterator*)self;
return iter->current != NULL;
}
// 链表迭代器:获取下一个元素
static void* list_next(Iterator* self) {
ListIterator* iter = (ListIterator*)self;
if (!iter->current) return NULL;
void* data = iter->current->data;
iter->current = iter->current->next; // 移动到下一个节点
return data;
}
// 销毁链表迭代器
static void list_iterator_destroy(Iterator* self) {
free(self);
}
// 链表聚合创建迭代器
static Iterator* linked_list_create_iterator(Aggregate* self) {
LinkedList* list = (LinkedList*)self;
ListIterator* iter = (ListIterator*)malloc(sizeof(ListIterator));
if (!iter) return NULL;
// 绑定迭代器接口方法
iter->iterator.has_next = list_has_next;
iter->iterator.next = list_next;
iter->iterator.destroy = list_iterator_destroy;
// 初始化遍历位置(从头节点开始)
iter->list = list;
iter->current = list->head;
return (Iterator*)iter;
}
// 销毁链表聚合(仅释放链表结构,不释放data,避免二次释放)
static void linked_list_destroy(Aggregate* self) {
LinkedList* list = (LinkedList*)self;
ListNode* node = list->head;
while (node) {
ListNode* temp = node;
node = node->next;
free(temp); // 释放节点,不释放data(由外部管理)
}
free(list);
}
// 创建链表聚合
LinkedList* linked_list_create() {
LinkedList* list = (LinkedList*)malloc(sizeof(LinkedList));
if (!list) return NULL;
// 初始化链表
list->head = NULL;
list->tail = NULL;
list->size = 0;
// 绑定聚合接口方法
list->aggregate.create_iterator = linked_list_create_iterator;
list->aggregate.destroy = linked_list_destroy;
return list;
}
步骤4:实现具体聚合与迭代器(数组)
4.1 数组聚合
c
// 具体聚合:数组
typedef struct {
Aggregate aggregate; // 继承聚合接口
void** data; // 元素数组(存储指针)
int size; // 当前元素数量
int capacity; // 容量
} Array;
// 数组添加元素(自动扩容)
void array_add(Array* arr, void* data) {
if (arr->size >= arr->capacity) {
// 扩容为原来的2倍
int new_cap = arr->capacity == 0 ? 4 : arr->capacity * 2;
void** new_data = (void**)realloc(arr->data, new_cap * sizeof(void*));
if (!new_data) return;
arr->data = new_data;
arr->capacity = new_cap;
}
arr->data[arr->size++] = data;
}
4.2 数组迭代器
c
// 具体迭代器:数组迭代器
typedef struct {
Iterator iterator; // 继承迭代器接口
Array* arr; // 关联的数组
int index; // 当前遍历索引
} ArrayIterator;
// 数组迭代器:判断是否有下一个元素
static bool array_has_next(Iterator* self) {
ArrayIterator* iter = (ArrayIterator*)self;
return iter->index < iter->arr->size;
}
// 数组迭代器:获取下一个元素
static void* array_next(Iterator* self) {
ArrayIterator* iter = (ArrayIterator*)self;
if (iter->index >= iter->arr->size) return NULL;
return iter->arr->data[iter->index++]; // 返回当前元素并移动索引
}
// 销毁数组迭代器
static void array_iterator_destroy(Iterator* self) {
free(self);
}
// 数组聚合创建迭代器
static Iterator* array_create_iterator(Aggregate* self) {
Array* arr = (Array*)self;
ArrayIterator* iter = (ArrayIterator*)malloc(sizeof(ArrayIterator));
if (!iter) return NULL;
// 绑定迭代器接口方法
iter->iterator.has_next = array_has_next;
iter->iterator.next = array_next;
iter->iterator.destroy = array_iterator_destroy;
// 初始化遍历索引(从0开始)
iter->arr = arr;
iter->index = 0;
return (Iterator*)iter;
}
// 销毁数组聚合(仅释放数组结构,不释放data)
static void array_destroy(Aggregate* self) {
Array* arr = (Array*)self;
free(arr->data); // 释放数组指针
free(arr);
}
// 创建数组聚合
Array* array_create() {
Array* arr = (Array*)malloc(sizeof(Array));
if (!arr) return NULL;
// 初始化数组
arr->data = NULL;
arr->size = 0;
arr->capacity = 0;
// 绑定聚合接口方法
arr->aggregate.create_iterator = array_create_iterator;
arr->aggregate.destroy = array_destroy;
return arr;
}
步骤5:使用迭代器模式
客户端通过统一的迭代器接口遍历不同聚合(链表和数组),无需关心内部结构。
c
// 客户端函数:统一遍历聚合
void traverse_aggregate(Aggregate* aggregate) {
// 获取迭代器
Iterator* iter = aggregate->create_iterator(aggregate);
if (!iter) return;
// 遍历元素
printf("遍历元素:");
while (iter->has_next(iter)) {
int* data = (int*)iter->next(iter); // 假设元素为int类型
printf("%d ", *data);
}
printf("\n");
// 销毁迭代器
iter->destroy(iter);
}
int main() {
// 1. 测试链表聚合
printf("=== 链表遍历 ===\n");
LinkedList* list = linked_list_create();
int a = 1, b = 2, c = 3;
linked_list_add(list, &a);
linked_list_add(list, &b);
linked_list_add(list, &c);
traverse_aggregate((Aggregate*)list);
list->aggregate.destroy((Aggregate*)list);
// 2. 测试数组聚合
printf("\n=== 数组遍历 ===\n");
Array* arr = array_create();
int d = 4, e = 5, f = 6;
array_add(arr, &d);
array_add(arr, &e);
array_add(arr, &f);
traverse_aggregate((Aggregate*)arr);
arr->aggregate.destroy((Aggregate*)arr);
return 0;
}
输出结果
=== 链表遍历 ===
遍历元素:1 2 3
=== 数组遍历 ===
遍历元素:4 5 6
核心思想总结
- 统一遍历接口 :无论聚合是链表、数组还是其他结构,客户端都通过
has_next和next方法遍历,屏蔽了内部实现差异。 - 解耦聚合与遍历 :聚合对象无需暴露内部结构(如链表的
head、数组的data),迭代器负责所有遍历逻辑,符合信息隐藏原则。 - 支持多种遍历方式:同一聚合可创建多个不同迭代器(如正向遍历、反向遍历),客户端按需选择。
C语言通过结构体封装迭代逻辑和聚合数据,结合函数指针提供统一接口,完美实现了迭代器模式的核心。这种模式适合需要遍历复杂数据结构(如树、图、自定义容器)且希望简化客户端操作的场景。