C言語で デザインパターンにトライ！　その6. Mediatorパターン ～煩雑になりがちなクラス管理を整理する

## **はじめに**

「C言語でトライ！ デザインパターン」
今回はMediatorパターンです。

概要を見ても面白そうでしたが、深堀するうちに思っていた以上によくできた構成だなと感じました。
こういった管理者的な役割のクラスがいると、結合度が低くなるのもどうですが、親のドキュメントだけちゃんと書いてあればそれだけでシステムの理解に繋がったり、仕事の担当分けもしやすかったりと思わぬメリットは多い印象なんですよね。

[デザインパターン一覧](https://qiita.com/developer-kikikaikai/items/8e7858c130c8ae8df488)
[作成したライブラリパッケージの説明](https://qiita.com/developer-kikikaikai/items/a8e6cc2739b7d8c64a3c)
公開コードサンプルは[こちら](https://github.com/developer-kikikaikai/design_patter_for_c_appendix), ライブラリパッケージは[こちら](https://github.com/developer-kikikaikai/design_pattern_for_c)

## **その6. Mediatorパターン**

wikipegiaより抜粋。

>Mediator パターン は、ソフトウェアのデザインパターンの一つで、統一されたインタフェース のセットを提供するパターンである。
>中略
>通常、プログラムは複数の（時には多数の）クラスからなり、ロジックと計算がクラスに配置される。しかし、プログラムでクラスの数が増えるに従い、特に保守やリファクタリングをする際、クラス間の通信の問題が複雑になり、プログラムを読んだり保守したりすることが困難になる。さらに、他のクラスに影響を与える可能性があるため、変更も難しくなる。
>
>Mediator パターンを用いると、オブジェクト間の通信は mediator によってカプセル化され、オブジェクト同士で直接通信せず、mediator を介して行うようになる。これにより通信するオブジェクト同士の依存関係を削減し、結合の度合いを下げることができる。

Managerのような仲介管理者を作って、煩雑になりそうな処理をまとめようって感じですね。
と思いながら色々な方の説明を見ていると何か違和感。

[@hikaoさんの記事](https://qiita.com/hikao/items/71fb454ed9b1164daa5b)に書かれているクラス図の例をお借りします。
![Mediatorパターン例](https://camo.qiitausercontent.com/48de3290ff76c24bde6d39e48400946d07ef34bb/687474703a2f2f7777772e69652e752d7279756b79752e61632e6a702f253745653038353733392f5f696d616765732f64657369676e7061747465726e2d6d65646961746f723031322e676966)

このクラス図での想定としては、
1. ユーザーは`Mediator`を作成
2. `Mediator`に利用したい`Colleague`クラスを追加。この例では`Colleague`が親の`Mediator`を保持します。通知用。
3. `Mediator`の`consultation`メソッドにより、各`Colleague`は自分の状態を通知する。
4. `Mediator`は通知に合わせて必要な状態に各`Colleague`を変更する(ここではadvice発行先を変える)

`Observer`にちょっと近いけど、こちらのポイントは**Colleague->Mediatorのコール後の処理はMediator内が判断して行う**という点ですね。
**画面描画のコントロール**や管理モジュールの状態管理等を行うのによさそうですね。
組み込みで言うなら、最小限のやり取りだけなのに依存関係が生まれてしまっているような、煩雑なシステムを整理するのに使えるかも。

###**似たようなケース？ MVPパターン**

UIに強いパターンということで、少ない知識の中から何か似たようなものがないかな～と探ったところ、1つ見つけました。
**MVP(Model-View-Presenter)**という、表示を司るView, Viewを管理するPresenter, 画面表示の元ネタ取得や操作を行うModelという3つの構成からなる、UI向けのデザインの1つです。Androidに触った際に出会いました。
この**ViewとPresenterの関係**の考え方も、ちょっとMediatorパターンと似ているなと思いました。

<img width="800" alt="MVP.png" src="https://qiita-image-store.s3.amazonaws.com/0/252277/af3faa76-133f-1686-3d5c-6f82b1ea1972.png">

UI界隈でよく耳にするMVCはViewが入力、Controllerが出力を行いますが、MVPは違います。画面からの入力はViewから各Viewを管理しているPresenterに転送。PresenterがModelを利用しながらViewの表示/非表示を切り替えます。
**Mediator=Presenter, Colleague=Viewの構図に近い気がしませんか？**

####**AndroidとMVP**

Androidのざっくりとした動作はこんな感じです。
1. LayoutにViewを配置する。(xmlにレイアウト記載 + コード上でもViewの追加)
2. 画面生成時に作られるクラス(Activityクラスと呼ばれます)内の処理で、Viewのタッチイベントを登録する。
3. ユーザー操作時にタッチイベントを拾い、画面を切り替えるなどの操作を行う。

Webページと比較するとこんな違いが見受けられますね。
1. 画面生成: **WebはHTML**が行うのに対し、**Androidはxml + Activityクラス**が行う。
2. ボタン操作等: **WebはHTML⇒javascriptで行う**のに対し、**AndroidはViewクラスに登録されたメソッド**で行う。

Androidは入口がクラスになっています。これで何も考えずに実装すると、画面を描写するActivityクラスにViewがわんさか。そのイベントもViewと紐づけるのでActivityクラスに定義。と、Activityクラスが凄いことに。
そこで、入力最初は仕様上しょうがないとして、**Viewの管理はPresenter**、**Presenterの指示のもとViewは画面に集中！**
のようなMVPもとい`Mediator`パターンチックなデザインが相性いいのかも。

## **サンプル**

Mediator内で閉じた動作をしたいということで、ライブラリ化は断念。凄い抽象化しまくれば実現出来るかもしれませんが、そんなの意味がない。
ということでサンプルにしました。これも悩みました。

CはUI苦手だし、状態監視が面白いサンプルは構成が複雑だし。。。
振る舞いの変化が表現できるRPGの戦闘AI風プログラムにしました。

Ubuntu 18.04で動作確認。

"mediator"=>戦闘AI的な感じ。メンバーたちを使って攻撃したり、敵からのダメージは`mediator_damage`で伝えます。
HPが0になったら離脱。`mediator_status_e`の作戦名によってちょっと振る舞いが変わったり

```C:mediator.h
#include "colleague.h"

struct mediator_t;
typedef struct mediator_t *Mediator;
typedef enum mediator_status_e {
        GANGAN_IKOZE,
        INOCHI_DIJINI,
} mediator_status_e;

Mediator mediator_new(mediator_status_e status);
//colleagueの追加
void mediator_add_colleague(Mediator this, Colleague colleague);
//自身パーティーの攻撃
int mediator_ownturn(Mediator this);
//メンバーのピンチ報告
void mediator_member_warning(Mediator this);
//敵からの攻撃
void mediator_damage(Mediator this, int value);
//メンバーチェック
int mediator_is_member(Mediator this);
void mediator_free(Mediator this);
```

"colleague"=>キャラクター。JOBによって出来ることが違ったりします。
"mediator"が`Colleague`のIFを介して、ATTACK, DEFENSE, HEALの指示をしてきます。

```C:colleague.h
typedef enum action_e {
        ATTACK,
        DEFENSE,
        HEAL,
} action_e;

typedef enum job_e {
        WARRIOR,
        PRIEST,
        WITCH,
} job_e;

struct colleague_t;
typedef struct colleague_t *Colleague;

struct colleague_t {
        job_e (*getjob)(Colleague this);
        int (*gethp)(Colleague this);
        int (*getcurhp)(Colleague this);
        int (*action)(Colleague this, action_e action);
        void (*damage)(Colleague this, int value);
};
```

`colleague`はHPが低くなったら`mediator_member_warning`でピンチであることを伝えることがあります。
それによってmediatorが回復指示を出したりします。

#### コード

一応[ここ](https://github.com/developer-kikikaikai/design_pattern_for_c/tree/master/mediator/sample)
ゲーム自体はオート戦闘だし、あほみたいにつまらないです。

## **感想**

デザインは目的があってのものだなと強く感じました。
解決したい問題があってこそ輝くわけだし。
でもすごく自然な発想のいいパターンなので、コードがごちゃごちゃしがちなC言語にも合いそうな気がします。

## **参考:**

Mediatorパターンの参考: 図もお借りしました。
https://qiita.com/hikao/items/71fb454ed9b1164daa5b

他の参考サイト
http://www.techscore.com/tech/DesignPattern/Mediator.html/
http://marupeke296.com/DP_Mediator.html


Android MVPパターンに関する参考サイト
http://konifar.hatenablog.com/entry/2015/04/17/010606
Android MVPパターンに関するわかりやすい説明
https://www.slideshare.net/yudaiyokoyama3/ss-41283302
特にP.15