C# Bridgeパターンについて理解する

## はじめに

今回はBridgeパターンについて簡単な実装例をもとに理解していく。
余談ですが、ほんとはAbstract Factoryについてを先に書く予定でしたが、気分的にこっちを先に書きたくなったのでこっちを書いています。なので次回はAbstract Factoryで

## Bridgeパターン
ブリッジパターンとは、抽象化（Abstraction）と実装（Implementation）を分離し、それぞれを独立して変更できるようにしたものです。
クラス階層の拡張や変更が容易になり、新しい実装を導入する際にも影響を最小限に抑えることができるメリットがあります。

## 設計・実装
今回は時間帯ごとに決まった挨拶を出力するような実装を考えました。設計は以下の通りです。
![2023-08-29_00h04_27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3131319/0e809bb1-bc5e-d557-a82d-9cab5db72a49.png)

ただ今回は後から気が付いたのですが大失敗しました。
GetNowTimeSlotではカルチャを設定して、現地時刻で今はおはようなのかといった風に時間によって適用な挨拶を出力したかったんです。
言語ごとにカルチャが違うからとはじめは考えていたんですが、普通に考えれば英語だからと言ってカルチャは一意に特定できないですよね・・・

今回はこれで実装してしまったんで、英語はアメリカでしかない・・・(よくないなぁ)
EnglishじゃなくてAmericaにすれば何とか・・・　
とりあえず失敗している部分は目をつむっていただいて...実装行きます。


    public abstract class Output
    {
        /// <summary>
        /// 挨拶を表す抽象クラス
        /// </summary>
        protected Greet m_Greet;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="greet"></param>
        protected Output(Greet greet)
        {
            m_Greet = greet;
        }

        /// <summary>
        /// 挨拶を出力する
        /// </summary>
        public abstract void OutputGreet();

    }

    public class OutputConsole : Output
    {

        public OutputConsole(Greet greet) : base(greet)
        {
        }

        public override void OutputGreet()
        {
            Console.WriteLine(m_Greet.GetGreet());
        }
    }

    public abstract class Greet
    {
        /// <summary>
        /// 挨拶を取得する
        /// </summary>
        /// <returns></returns>
        public abstract string GetGreet();

        /// <summary>
        /// 現在の時間帯を取得する
        /// 各国の現在時刻を取得して、それに応じて挨拶を変える
        /// </summary>
        /// <returns></returns>
        protected abstract TimeSlot GetNowTimeSlot();
    }

    public class JapaneseGreet : Greet
    {
        /// <summary>
        /// 朝の挨拶
        /// </summary>
        private string Morning = "おはよう";

        /// <summary>
        /// 昼の挨拶
        /// </summary>
        private string Noon = "こんにちは";

        /// <summary>
        /// 夜の挨拶
        /// </summary>
        private string Night = "こんばんは";


        public override string GetGreet()
        {
            // 現在の時間帯に応じて挨拶を変える
            var nowTimeSlot = GetNowTimeSlot();

            switch (nowTimeSlot)
            {
                case TimeSlot.Morning:
                    return Morning;
                case TimeSlot.Noon:
                    return Noon;
                case TimeSlot.Night:
                    return Night;
                default:
                    throw new NotImplementedException();
            }
        }

        protected override TimeSlot GetNowTimeSlot()
        {
            // 現在の時間を取得する
            // 日本語のなのでカルチャ設定はいらない
            DateTime now = DateTime.Now;
            int hour = now.Hour;

            // 時間に応じて、挨拶を返す
            if (hour >= 4 && hour < 10)
            {
                return TimeSlot.Morning;
            }
            else if (hour >= 10 && hour < 17)
            {
                return TimeSlot.Noon;
            }
            else
            {
                return TimeSlot.Night;
            }
        }
    }

とまぁこんな感じです。
核になる部分だけ載せました。あとはメインから呼ぶだけです。
Greetの具象クラスにのメソッドを見ると、ベースクラスに切り出して実装したほうがよさそうな箇所がちらほら。
後から何かと気が付きますね。修正はしておきます・・・　


メインで日本語のコンソール出力を呼び出すと、夜にビルドしたのでコンソールには「こんばんは」と表示されました！

## おわり
今回はBridgeパターンについて実装しました。
ちょっと設計の時点で、カルチャのところでだいぶ間違った認識してしまっていましたが、Bridgeパターンの実装としては勉強になりました。
引き続きデザインパターンの学習を進めていきたいと思います。