Facadeパターン

デザインパターン【C#】:Facade 02_複雑なサブシステムに対して実装する

今回から、Facadeパターンの実装例を見ていきます。あらかじめVisual Studio 2019で「Machine」と「Machine.UI」という2つのプロジェクトを用意しています。これらはこの後のレクチャーでダウンロードできるようにしておくので、実際に手元で動かしながら確認してください。

図1 ソリューション構成(Machineプロジェクトと Machine.UI プロジェクト)

「Machine」プロジェクトには Box・Camera・Fan・FanEntity・Power といった複数のクラスが用意されています。「Machine.UI」プロジェクトには画面(Form1)が1つあるだけで、こちらにはまだ何も実装していません。

図2 Machine.UI プロジェクトの Form1(現時点では何も配置していない空の画面)

Machineプロジェクト=「複雑なサブシステム」の例

この講座では、「Machine」プロジェクトを複雑なサブシステムに見立てて話を進めます。Machineは何らかの装置というイメージで、装置内部の温度を取得したり、Fan(ファン)の速度を取得したり、ファンを起動・停止したり、電源を入れたりといった操作ができるようになっています。

今回サンプルとして用意したのはこの程度の規模ですが、実際の現場ではもっとクラスの数が多く、もっとごちゃごちゃとしていて「何がどうなっているのかよく分からない」ような、より複雑なサブシステムになっていると想定してください。それでも今回のサンプルだけでも、「どのクラスを」「どういう手順で」使えばいいのか迷うには十分な状態になっています。

図3 Box.cs 内部温度・外部温度を取得するクラス

namespace Machine
{
    public class Box
    {
        private Random _random = new Random();
 
        public int GetInternalTemperature()
        {
            return _random.Next(10, 80);
        }
 
        public int GetExternalTemperature()
        {
            return _random.Next(10, 80);
        }
    }
}

 

図4 Camera.cs 撮影を行うクラス

namespace Machine
{
    public class Camera
    {
        public void Take()
        {
        }
    }
}

 

図5 Fan.cs ファンの回転数取得・起動・停止を行うクラス

namespace Machine
{
    public class Fan
    {
        private Random _random = new Random();
 
        public FanEntity GetSpin(int fanId)
        {
            return new FanEntity(fanId, _random.Next(0, 3000));
        }
 
        public void Start(int fanId)
        {
        }
 
        public void Stop(int fanId)
        {
        }
    }
}

画面側からMachineを参照する

Machine.UI プロジェクトの参照設定で Machine プロジェクトを追加し、UI側のコードから Machine プロジェクトのクラスを見られる状態にしておきます。

図6 参照マネージャーで Machine プロジェクトを参照に追加する

この状態で Form1_Load メソッドの中に「Machine.」と入力してみると、Box・Camera・Fan・FanEntity・Power…といったクラスがずらっとインテリセンスに表示されます。

図7 「Machine.」と入力すると多数のクラスが一覧表示される

ここで「どれを使えばいいのか」「どういう手順で使えばいいのか」がぱっと見て分からない状態になっているのが分かると思います。

試しにFanクラスを使ってみる

試しにFanクラスを1つ使ってみます。Fanクラスをnewし、「.」と入力するとGetSpin・Start・Stop等のメソッドが表示され、GetSpinには「int fanId」という引数が必要なことがツールチップで分かります。

図8 fan.GetSpin(int fanId) のシグネチャがツールチップで表示される

fanIdには適当に 4 を渡してみると、戻り値としてFanEntityが返ってくることが確認できます。

図9 Fanクラスを生成し GetSpin(4) を呼び出した最終的なコード

private void Form1_Load(object sender, EventArgs e)
{
    var fan = new Machine.Fan();
    FanEntity entity = fan.GetSpin(4);
}

まとめ:使う側に知識が必要という問題

このように、今は画面(UI)側から直接Machineプロジェクトのクラスを使っていますが、これだと使う側にちゃんとした知識がないと実装できません。「Fanクラスをnewして、GetSpinを呼んで…」といった手順そのものを、使う側が理解していなければならないからです。もし手順がもっと複雑だったら、「どういう順番で何を呼べばいいのか」がさらに分かりづらい状態になってしまいます。

次回以降、この「使う側が複雑なサブシステムの内部を知らないと使えない」という問題を、Facadeパターンでどう解消していくかを見ていきます。

C#文法:コレクション

■非公開コース「C#14新機能」プレゼント:
非公開コース「C#14新機能」(80分)をご覧になりたい方は
こちらからURLとパスワードを発行していますので、ご覧になってみてください。
非公開コース「C#14新機能」を観る

A01_はじめに
A02_プロジェクトの作成
B01_配列とは
B02_配列の生成とアクセス
B03_生成と同時に値を設定する
B04_型推論による生成
B05_メソッドの引数などにする場合の注意点
B06_Length
B07_IndexOfでの検索
B08_FindIndexでの検索
B09_Find
B10_Exists
B11_FindAllとFindLast
B12_誤ったコピー
B13_Array.Copy
B14_範囲指定のコピー
B15_Resize
C01A_ArrayList
C02_List
C03_List 動的な要素の変更
C04_Listのコンストラクタ
C05_Listのコンストラクタ_Capacity
C06_ListTからArrayクラスのメソッドが呼ばれている
D01_コレクションインタフェースとは
D02_異なるコレクションクラスに互換性を持たせる
D03_インタフェースの階層構造
D04_クライアントができる操作を制限させる
D05_クライアントができる操作を制限させる_後半
D06_Enumerableの拡張メソッドに関して
D07_ReadOnly系のコレクションインタフェース
D08_AsReadOnly
D09_ToListでコピーする
D10_ListTはprivateで使う

■非公開コース「C#14新機能」プレゼント:
非公開コース「C#14新機能」(80分)をご覧になりたい方は
こちらからURLとパスワードを発行していますので、ご覧になってみてください。
非公開コース「C#14新機能」を観る