大话设计模式C语言之迭代器模式 迭代器模式
迭代器模式 (IteratorPattern) 是一种行为设计模式,让你能在不暴露集合底层表现形式(列表、栈和树等)的情况下遍历集合中所有的元素。
案例代码 迭代器 迭代器对外接口 iterator.h
迭代器(Iterator)接口声明了遍历集合所需的操作:获取下一个元素、获取当前位置和重新开始迭代等。
1 2 3 4 5 6 7 8 9 10 11 12 13 #ifndef ITERATOR_H #define ITERATOR_H typedef struct Iterator Iterator ;int iterator_first (Iterator *it) ;int iterator_next (Iterator *it) ;int iterator_is_done (Iterator *it) ;int iterator_current (Iterator *it) ;void iterator_destroy (Iterator *it) ;#endif
迭代器内部抽象接口 iterator_internal.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #ifndef ITERATOR_INTERNAL_H #define ITERATOR_INTERNAL_H #include "iterator.h" Iterator *iterator_create ( void *impl, int (*first)(void *), int (*next)(void *), int (*is_done)(void *), int (*current)(void *), void (*destroy)(void *) ) ;#endif
迭代器实现 iterator.c
具体迭代器(Concrete Iterators)实现遍历集合的一种特定算法。迭代器对象必须跟踪自身遍历的进度。这使得多个迭代器可以相互独立地遍历同一集合。
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 47 48 49 50 51 52 53 54 55 #include <stdlib.h> #include "iterator_internal.h" struct Iterator { void *impl; int (*first)(void *); int (*next)(void *); int (*is_done)(void *); int (*current)(void *); void (*destroy)(void *); }; int iterator_first (Iterator *it) { return it->first(it->impl); } int iterator_next (Iterator *it) { return it->next(it->impl); } int iterator_is_done (Iterator *it) { return it->is_done(it->impl); } int iterator_current (Iterator *it) { return it->current(it->impl); } void iterator_destroy (Iterator *it) { if (!it) return ; it->destroy(it->impl); free (it); } Iterator *iterator_create ( void *impl, int (*first)(void *), int (*next)(void *), int (*is_done)(void *), int (*current)(void *), void (*destroy)(void *) ) { Iterator *it = malloc (sizeof (*it)); if (!it) return NULL ; it->impl = impl; it->first = first; it->next = next; it->is_done = is_done; it->current = current; it->destroy = destroy; return it; }
集合 集合抽象接口 aggregate.h
集合(Collection)接口声明一个或多个方法来获取与集合兼容的迭代器。 请注意返回方法的类型必须被声明为迭代器接口,因此具体集合可以返回各种不同种类的迭代器。
1 2 3 4 5 6 7 8 9 10 11 #ifndef AGGREGATE_H #define AGGREGATE_H typedef struct Aggregate Aggregate ;typedef struct Iterator Iterator ;Iterator *aggregate_create_iterator (Aggregate *agg) ;void aggregate_destroy (Aggregate *agg) ;#endif
动态数组集合 int_array.c
具体集合(Concrete Collections)会在客户端请求迭代器时返回一个特定的具体迭代器类实体。
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 #include <stdlib.h> #include <string.h> #include "aggregate.h" #include "iterator_internal.h" typedef struct { int *data; size_t size; } IntArray; struct Aggregate { void *impl; Iterator *(*create_iterator)(void *); void (*destroy)(void *); }; static void int_array_destroy (void *impl) { IntArray *arr = impl; free (arr->data); free (arr); } typedef struct { IntArray *array ; size_t index; } IntArrayIterator; static int arr_first (void *impl) { ((IntArrayIterator *)impl)->index = 0 ; return 0 ; } static int arr_next (void *impl) { ((IntArrayIterator *)impl)->index++; return 0 ; } static int arr_is_done (void *impl) { IntArrayIterator *it = impl; return it->index >= it->array ->size; } static int arr_current (void *impl) { IntArrayIterator *it = impl; return it->array ->data[it->index]; } static void arr_it_destroy (void *impl) { free (impl); } static Iterator *int_array_create_iterator (void *impl) { IntArrayIterator *real = malloc (sizeof (*real)); real->array = impl; real->index = 0 ; return iterator_create( real, arr_first, arr_next, arr_is_done, arr_current, arr_it_destroy ); } Aggregate *int_array_create (const int *data, size_t size) { Aggregate *agg = malloc (sizeof (*agg)); IntArray *arr = malloc (sizeof (*arr)); arr->data = malloc (sizeof (int ) * size); memcpy (arr->data, data, sizeof (int ) * size); arr->size = size; agg->impl = arr; agg->create_iterator = int_array_create_iterator; agg->destroy = int_array_destroy; return agg; } Iterator *aggregate_create_iterator (Aggregate *agg) { return agg->create_iterator(agg->impl); } void aggregate_destroy (Aggregate *agg) { if (!agg) return ; agg->destroy(agg->impl); free (agg); }
链表集合 linked_list.c 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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 #include <stdlib.h> #include "aggregate.h" #include "iterator_internal.h" typedef struct Node { int value; struct Node *next ; } Node; typedef struct { Node *head; } LinkedList; struct Aggregate { void *impl; Iterator *(*create_iterator)(void *); void (*destroy)(void *); }; static void list_destroy (void *impl) { LinkedList *list = impl; Node *cur = list ->head; while (cur) { Node *tmp = cur; cur = cur->next; free (tmp); } free (list ); } typedef struct { Node *current; } ListIterator; static int list_first (void *impl) { (void )impl; return 0 ; } static int list_next (void *impl) { ListIterator *it = impl; if (it->current) it->current = it->current->next; return 0 ; } static int list_is_done (void *impl) { return ((ListIterator *)impl)->current == NULL ; } static int list_current (void *impl) { return ((ListIterator *)impl)->current->value; } static void list_it_destroy (void *impl) { free (impl); } static Iterator *list_create_iterator (void *impl) { LinkedList *list = impl; ListIterator *real = malloc (sizeof (*real)); real->current = list ->head; return iterator_create( real, list_first, list_next, list_is_done, list_current, list_it_destroy ); } Aggregate *linked_list_create (const int *data, size_t size) { Aggregate *agg = malloc (sizeof (*agg)); LinkedList *list = malloc (sizeof (*list )); list ->head = NULL ; for (int i = (int )size - 1 ; i >= 0 ; --i) { Node *n = malloc (sizeof (*n)); n->value = data[i]; n->next = list ->head; list ->head = n; } agg->impl = list ; agg->create_iterator = list_create_iterator; agg->destroy = list_destroy; return agg; }
测试客户端代码 main.c 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 #include <stdio.h> #include "aggregate.h" #include "iterator.h" Aggregate *int_array_create (const int *, size_t ) ;Aggregate *linked_list_create (const int *, size_t ) ;static void test (Aggregate *agg) { Iterator *it = aggregate_create_iterator(agg); for (iterator_first(it); !iterator_is_done(it); iterator_next(it)) { printf ("%d " , iterator_current(it)); } printf ("\n" ); iterator_destroy(it); aggregate_destroy(agg); } int main (void ) { int data[] = {1 , 2 , 3 , 4 , 5 }; test(int_array_create(data, 5 )); test(linked_list_create(data, 5 )); while (1 ); return 0 ; }
总结 单一职责原则。通过将体积庞大的遍历算法代码抽取为独立的类,你可对客户端代码和集合进行整理。开闭原则。 你可实现新型的集合和迭代器并将其传递给现有代码, 无需修改现有代码。你可以并行遍历同一集合,因为每个迭代器对象都包含其自身的遍历状态。