C言語でBridgeパターン【オブジェクト指向】

C言語でGoFのBridgeパターンを実装します。

Bridgeパターンを確認する

まずはBridgeパターンを確認しましょう。TECHSCOREさんのBridgeパターンの解説記事をご参照ください。

 

https://www.techscore.com/tech/DesignPattern/Bridge.html/

 

Bridgeパターンで設計する

TECHSCOREさんのサンプルコードをC言語に移植します。クラス図にすると次のようになります。

 

Bridgeパターンのクラス図

 

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でバブルソートを重複して作ることはしていません。

 

目次:C言語でGoFのデザインパターン【オブジェクト指向】

ソースコード:https://github.com/yuksblog/c_gof_design_pattern