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); }