C言語でGoFのBridgeパターンを実装します。
Bridgeパターンを確認する
まずはBridgeパターンを確認しましょう。TECHSCOREさんのBridgeパターンの解説記事をご参照ください。
https://www.techscore.com/tech/DesignPattern/Bridge.html/
Bridgeパターンで設計する
TECHSCOREさんのサンプルコードをC言語に移植します。クラス図にすると次のようになります。

Bridgeパターンで実装する
SortImplを作る
まずは実際にソート処理を行うSortImpl系統を作っていきましょう。AbstractなSortImplは次のように作ります。
SortImpl.h
typedef struct SortImpl {
void (*sort)(struct SortImpl *impl, uint16_t *list);
} SortImpl;
extern void SortImpl_sort(SortImpl *impl, uint16_t *list);
SortImpl.c
void SortImpl_sort(SortImpl *impl, uint16_t *list) {
impl->sort(impl, list);
}
QuickSortImplを作る
SortImplの実装クラスの1つQuickSortImplを作りましょう。
QuickSortImpl.h
typedef struct QuickSortImplStruct QuickSortImpl; extern QuickSortImpl *QuickSortImpl_create(); extern void QuickSortImpl_destroy(QuickSortImpl *impl);
QuickSortImpl.c
typedef struct QuickSortImplStruct {
SortImpl super;
} QuickSortImplStruct;
static void sort(SortImpl *impl, uint16_t *list) {
// do quick sort
}
QuickSortImpl *QuickSortImpl_create() {
QuickSortImpl *quick = (QuickSortImpl*)malloc(sizeof(QuickSortImpl));
quick->super.sort = sort;
return quick;
}
void QuickSortImpl_destroy(QuickSortImpl *impl) {
free(impl);
}
もう1つの実装クラスであるBubbleSortImplも同様にして作れますので、ここでは省略します。
Sorterを作る
SortImplを使用するSorterを作りましょう。Sorterは機能追加されるので、継承したクラスから参照できるように構造体の仕様はSorterPrivate.hに入れておきます。
Sorter.h
typedef struct SorterStruct Sorter; extern Sorter *Sorter_create(SortImpl *impl); extern void Sorter_destroy(Sorter *sorter); extern void Sorter_sort(Sorter *sorter, uint16_t *list);
SorterPrivate.h
typedef struct SorterStruct {
SortImpl *impl;
} SorterStruct;
Sorter.c
Sorter *Sorter_create(SortImpl *impl) {
Sorter *sorter = (Sorter*)malloc(sizeof(Sorter));
sorter->impl = impl;
return sorter;
}
void Sorter_destroy(Sorter *sorter) {
free(sorter);
}
void Sorter_sort(Sorter *sorter, uint16_t *list) {
SortImpl_sort(sorter->impl, list);
}
TimerSorterを作る
Sorterを継承し、timeSort()メソッドを機能追加するTimerSorterを作りましょう。
TimerSorter.h
typedef struct TimerSorterStruct TimerSorter; extern TimerSorter *TimerSorter_create(SortImpl *impl); extern void TimerSorter_destroy(TimerSorter *sorter); extern void TimerSorter_timerSort(TimerSorter *sorter, uint16_t *list);
TimerSorter.c
typedef struct TimerSorterStruct {
Sorter super;
} TimerSorterStruct;
TimerSorter *TimerSorter_create(SortImpl *impl) {
TimerSorter *sorter = (TimerSorter*)malloc(sizeof(TimerSorter));
sorter->super.impl = impl;
return sorter;
}
void TimerSorter_destroy(TimerSorter *sorter) {
free(sorter);
}
void TimerSorter_timerSort(TimerSorter *sorter, uint16_t *list) {
clock_t start = clock();
SortImpl_sort(sorter->super.impl, list);
clock_t end = clock();
printf("elapsed time = %ld\n", (end - start));
}
Sorterを使う場合と、TimerSorterを使う場合を見比べて、Bridgeパターンの効果を確認しておきましょう。
Sorterを使う場合
QuickSortImpl *impl = QuickSortImpl_create(); Sorter *sorter = Sorter_create((SortImpl*)impl); Sorter_sort(sorter, NULL); QuickSortImpl_destroy(impl); Sorter_destroy(sorter);
TimerSorterを使う場合
BubbleSortImpl *impl = BubbleSortImpl_create(); TimerSorter *sorter = TimerSorter_create((SortImpl*)impl); Sorter_sort((Sorter*)sorter, NULL); TimerSorter_timerSort(sorter, NULL); BubbleSortImpl_destroy(impl); TimerSorter_destroy(sorter);
Sorterの場合はクイックソートを使っています。TimerSorterの場合は、バブルソートを使いつつ、timerSort()メソッドの機能追加が実現できていますね。
もちろん、TimerSorterでバブルソートを重複して作ることはしていません。