1、定义
提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。
2、结构图
3、协作角色
Interator 定义访问遍历对象内部元素的接口
ConcreteInterator 实现Interator接口,在遍历时跟踪当前位置。
Aggregate 定义创建相应迭代器的接口
ConcreteAggregate 实现创建相应迭代器的接口,返回创建的迭代器的实例。
4、适用性
访问一个聚合对象内部元素而无需暴漏它的内部表示
支持对象的各种遍历。
为遍历不同的聚合结构提供一个统一的接口。
5、实例:
1、需求(引用head first 设计模式的是个例子)。一个早餐店收购一家午餐店(and so on)。所以现在有两份菜单,加入一份按照数组方式实现,一份是按照队列方式实现,现在要实现一个服务员对象,可以轻松实现按照客户需要打印一份菜单。
2、实现:
menu.h
#ifndef __MENU_H__
#define __MENU_H__
#define MENU_NAME_LEN 16
#define MENU_DESC_LEN 64
#define RET_SUCCESS 0
#define RET_FAIL (-1)
#define IS_VEG 1
#define NOT_VEG 0
typedef struct menu_s{
char name[MENU_NAME_LEN];
char desc[MENU_DESC_LEN];
int isVeg;
double price;
}menu_t;
typedef enum {
MENU_BF,
MENU_LUNCH
}MENU_TYPE;
int menu_item_init(menu_t *item, char *name, char *desc, int isVeg, double price);
char *menu_item_get_name(menu_t *item);
char *menu_item_get_desc(menu_t *item);
double menu_item_get_price(menu_t *item);
int menu_item_get_isVeg(menu_t *item);
#endif
menu.c
#include <stdio.h>
#include <string.h>
#include "menu.h"
int menu_item_init(menu_t *item, char *name, char *desc, int isVeg, double price)
{
if(NULL == item)
return RET_FAIL;
if((NULL != name)&&(strlen(name) < MENU_NAME_LEN))
memcpy(item->name, name ,strlen(name));
if((NULL != desc)&&(strlen(desc) < MENU_NAME_LEN))
memcpy(item->desc, desc ,strlen(desc));
item->isVeg = isVeg;
item->price = price;
return RET_SUCCESS;
}
char *menu_item_get_name(menu_t *item)
{
if(NULL == item)
return NULL;
return item->name;
}
char *menu_item_get_desc(menu_t *item)
{
if(NULL == item)
return NULL;
return item->desc;
}
double menu_item_get_price(menu_t *item)
{
if(NULL == item)
return 0;
return item->price;
}
int menu_item_get_isVeg(menu_t *item)
{
if(NULL == item)
return 0;
return item->isVeg;
}
pancakeMenu.h
#ifndef __PANCAKEMENU_H__
#define __PANCAKEMENU_H__
int lunch_menu_init();
menu_t* lunch_next();
int lunch_hasNext();
#endif
pancakeMenu.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "menu.h"
#include "pancakeMenu.h"
typedef struct lunch_menu_s {
menu_t lunch;
struct lunch_menu_s *next;
}lunch_menu_t;
lunch_menu_t lunch_head;
lunch_menu_t *lunch_cur;
static int lunch_add_item(char *name, char *desc, int isVeg, double price)
{
lunch_menu_t *item = NULL;
item = (lunch_menu_t *)malloc(sizeof(lunch_menu_t));
if(NULL == item)
{
return RET_FAIL;
}
menu_item_init(&(item->lunch),name, desc, isVeg,price);
item->next = lunch_head.next;
lunch_head.next = item;
return RET_SUCCESS;
}
int lunch_menu_init()
{
memset((void *)&lunch_head, 0, sizeof(lunch_menu_t));
lunch_head.next = NULL;
lunch_add_item("l1","this l1",IS_VEG,2.99);
lunch_add_item("l2","this l2",IS_VEG,2.69);
lunch_add_item("l3","this l3",NOT_VEG,7.99);
lunch_add_item("l4","this l4",IS_VEG,3.99);
lunch_cur = lunch_head.next;
return RET_SUCCESS;
}
menu_t* lunch_next()
{
menu_t *menu = &lunch_cur->lunch;
lunch_cur = lunch_cur->next;
return menu;
}
int lunch_hasNext()
{
return !(lunch_cur == NULL);
}
bfMenu.h
#ifndef __BFMENU_H__
#define __BFMENU_H__
int bf_menu_init();
menu_t* bf_next();
int bf_hasNext();
#endif
bfMenu.c
#include <stdio.h>
#include <string.h>
#include "menu.h"
#include "bfMenu.h"
#define ARR_SIZE 10
typedef struct {
menu_t breakfast[ARR_SIZE];
int used[ARR_SIZE];
int num;
}bf_menu_t;
bf_menu_t breakfast;
int bf_cur = 0;
static int bf_add_item(char *name, char *desc, int isVeg, double price)
{
unsigned int index;
unsigned int i;
for(i = 0; i < ARR_SIZE; i++)
{
if(breakfast.used[i] == 0)
{
menu_item_init(&breakfast.breakfast[i],name, desc, isVeg,price);
breakfast.used[i] = 1;
breakfast.num++;
return RET_SUCCESS;
}
}
return RET_FAIL;
}
int bf_menu_init()
{
memset((void *)&breakfast, 0, sizeof(breakfast));
bf_add_item("b1","this b1",IS_VEG,2.99);
bf_add_item("b2","this b2",IS_VEG,2.69);
bf_add_item("b3","this b3",NOT_VEG,7.99);
bf_add_item("b4","this b4",IS_VEG,3.99);
bf_cur = 0;
return RET_SUCCESS;
}
menu_t* bf_next()
{
int cur = bf_cur;
bf_cur++;
return (&breakfast.breakfast[cur]);
}
int bf_hasNext()
{
return !(bf_cur == breakfast.num);
}
iterator.h
#ifndef __ITERATOR_H__
#define __ITERATOR_H__
typedef struct {
menu_t* (*next)();
int (*hasNext)();
}iterator_t;
iterator_t *create_iterator(MENU_TYPE type);
#endif
iterator.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "menu.h"
#include "iterator.h"
#include "bfMenu.h"
#include "pancakeMenu.h"
iterator_t *create_iterator(MENU_TYPE type)
{
iterator_t *iterator = NULL;
iterator = (iterator_t *)malloc(sizeof(iterator_t));
if(NULL == iterator)
{
return NULL;
}
switch(type)
{
case MENU_BF:
bf_menu_init();
iterator->hasNext = bf_hasNext;
iterator->next = bf_next;
break;
case MENU_LUNCH:
lunch_menu_init();
iterator->hasNext = lunch_hasNext;
iterator->next = lunch_next;
break;
default:
break;
}
return iterator;
}
client.c
#include <stdio.h>
#include "menu.h"
#include "iterator.h"
int main()
{
iterator_t *iterator_bf = NULL;
iterator_t *iterator_lunch = NULL;
menu_t *item = NULL;
iterator_bf = create_iterator(MENU_BF);
printf("create bf %p\n",iterator_bf);
if(NULL == iterator_bf)
{
return 1;
}
while(iterator_bf->hasNext())
{
item = iterator_bf->next();
printf("name %s desc %s\n",menu_item_get_name(item),menu_item_get_desc(item));
}
iterator_lunch = create_iterator(MENU_LUNCH);
if(NULL == iterator_lunch)
{
return 1;
}
while(iterator_lunch->hasNext())
{
item = iterator_lunch->next();
printf("name %s desc %s\n",menu_item_get_name(item),menu_item_get_desc(item));
}
return 0;
}