Cでイテレータパターン

まずはアグリゲータインターフェイスに当たるヘッダファイル。宣言している関数はイテレータインスタンスを生成して返すCreateIterator関数。戻り値がIterator*であるためIterator.hをインクルードしている。このIterator.hはhasNext()とnext関数の宣言がされている。Iterator構造体の宣言だけがあればよいのだけれど、あまりヘッダファイルを階層に分けてもわかりにくいので今回はこれで良しとする。

#ifndef AGGREGATE_HEADER_FILE_INCLUDED__
#define AGGREGATE_HEADER_FILE_INCLUDED__

#include "Iterator.h"

/*!
	@brief	イテレータのコンストラクタ
	@param	p:コンクリートアグリゲータのインスタンスを指すポインタ
	@retval	生成したイテレータのインスタンスを指すポインタ
	@attention	実際の処理はコンクリートクラスにて実装のこと
	@attention	戻り値のインスタンスはDisposeIteratorで破棄すること
 */
Iterator *CreateIterator(void *p);

/*!
	@brief	イテレータデストラクタ
	@param	CreateIteratorで生成したイテレータインスタンスを指すポインタ
	@retval	なし
	@attention	実際の処理はコンクリートクラスにて実装のこと
 */
void DisposeIterator(Iterator *p);

#endif	/* End of AGGREGATE_HEADER_FILE_INCLUDED__ */

このアグリゲートの実装はBookShelf構造体となる。このBookShelf実装のためのヘッダファイル。BookShelf実装を外部に見せないために、構造体はタグの宣言だけを行い、操作はポインタを介してのみとする。BookShelfにはBookを格納するため、Book.hをインクルードする。

#ifndef BOOK_SHELF_HEADER_FILE_INCLUDED__
#define BOOK_SHELF_HEADER_FILE_INCLUDED__

#include "Book.h"
#include "Aggregate.h"

/*!
	@brief	コンクリートアグリゲータクラス
 */
typedef struct BookShelf_tag BookShelf;

/*!
	@brief	コンストラクタ
	@param	maxsize:本棚に格納できる本の数
	@retval	生成したBookShelfのインスタンスを指すポインタ
	@attention	戻り値のインスタンスはDisposeBookShelfで破棄すること
 */
BookShelf *CreateBookShelf(int maxsize);

/*!
	@brief	デストラクタ
	@param	p: BookShelfインスタンスを指すポインタ
	@attention	BookShelfに格納された本もまとめて破棄される
 */
void DisposeBookShelf(BookShelf *p);

/*!
	@brief	本棚にあるインデックスに対応した本のインスタンスを指すポインタを返す
	@param	p: BookShelfインスタンスを指すポインタ
	@param	index: 取得したい本のインデックス
	@retval	indexに対応した本のインスタンスを指すポインタ
	@attention	取得したポインタをfreeしないこと。ダングリングポインタとなってしまう。
 */
Book *GetBookAt(BookShelf *p, int index);

/*!
	@brief	本棚に本を加える
	@param	p: BookShelfインスタンスを指すポインタ
	@param	pBook: 本のインスタンスを指すポインタ
	@attention	本棚から本を取り除く関数は無い。BookShelfデストラクタで破棄すること
 */
void AppendBook(BookShelf *p, Book *pBook);

/*!
	@brief	本棚に格納した本の数を取得する
	@param	p: BookShelfインスタンスを指すポインタ
	@retval	本棚に格納した本の数
 */
int GetLength(BookShelf *p);

#endif

コンクリートアグリゲータBookShelfの実装ソースファイル

#include "BookShelf.h"
#include "BookShelfIterator.h"
#include <stdlib.h>

struct BookShelf_tag{
	Book **pBooks;
	int last;
};

BookShelf *CreateBookShelf(int maxsize)
{
	BookShelf *p = NULL;

	p = malloc(sizeof(BookShelf));
	if (p == NULL) {
		goto ERROR;
	}

	p->pBooks = malloc(sizeof(Book *) * maxsize);
	if (p->pBooks == NULL) {
		goto ERROR;
	}
	p->last = 0;
	
	return p;
ERROR:
	if (p != NULL) {
		free(p->pBooks);
	}
	free(p);
	
	return NULL;
}

void DisposeBookShelf(BookShelf *p)
{
	int i;
	if (p == NULL) {
		return;
	}

	for (i = 0; i < p->last; i++) {
		free(p->pBooks[i]);
	}
	
	free(p->pBooks);
	free(p);
}

Book *GetBookAt(BookShelf *p, int index)
{
	return p->pBooks[index];
}

void AppendBook(BookShelf *p, Book *pBook)
{
	p->pBooks[p->last] = pBook;
	p->last++;
}

int GetLength(BookShelf *p)
{
	return p->last;
}

/*!
	@brief	コンクリートイテレータのコンストラクタ
	@param	p:BokkShelfのインスタンスを指すポインタ
	@retval	生成したBookShelfItereatorインスタンスを指すポインタ
 */
Iterator *CreateIterator(void *p)
{
	return CreateBookShelfIterator(p);
}

/*!
	@brief	BookShelfIteratorデストラクタ
	@param	CreateBookShelfIteratorで生成したインスタンスを指すポインタ
	@retval	なし
 */
void DisposeIterator(Iterator *p)
{
	DisposeBookShelfIterator(p);
}