はじめに
GoFのデザインパターンの1つであるProxyパターンを体験してみました。
Proxyパターンとは
Proxyパターンとは、対象クラスの処理をそのクラス以外の代理人クラスが行うように処理にするデザインパターンです。 どうしても対象のクラスに処理を任せないといけないときのみ対象のクラスに処理を任せます。
登場人物は4つありますが、以下の記事の説明がとても分かりやすかったので引用させていただきます。
Proxy パターン - デザインパターン入門 - IT専科
- Subject(主体・本人) 「Proxy」と「RealSubject」の共通のインタフェースを定義します。上記により、双方のクラスを同一視でき、同じメソッドで「Proxy」が肩代わりできます。
- Proxy(代理人) 「Subject」のインタフェースを実装します。「Client」からの要求を可能な限り処理しますが、どうしても自分で処理できない場合は、「RealSubject」に処理を委任します。 ※「Proxy」は、どうしても「RealSubject」が必要になった時点で、「RealSubject」オブジェクトを生成し、処理を委任します。
- RealSubject(真の主体・本人) 「Subject」のインタフェースを実装します。「Proxy」では、どうしも処理できない場合に、「Proxy」から処理を委任されます。
- Client(利用者) 「Proxy」パターンを適用したクラスを利用し処理します。
(上記の記事より引用)
サンプルコード
以下は朝起きるのに時間がかかってしまう処理(重い処理と仮定します)をProxyパターンを用いて作成しているサンプルコードです。 各クラスに上記記事で引用させていただいた4つの登場人物をコメントで記載しています。
// Client(利用者) public class Program { static void Main() { IWakeUp wakeUp = new WakeUpProxy(); wakeUp.MorningCall(); wakeUp.WakeUpMorning(); } } // Subject(主体・本人) public interface IWakeUp { public void MorningCall() => Console.WriteLine("--- 朝 ---"); public void WakeUpMorning(); } // RealSubject(真の主体・本人) public class WakeUp : IWakeUp { public WakeUp() => Console.WriteLine($"{nameof(WakeUp)}インスタンスが生成されました。"); public void WakeUpMorning() { Thread.Sleep(2000); Console.WriteLine("眠いけど頑張って起きよう(´Д⊂ヽ"); } } // Proxy(代理人) // WakeupMorningメソッドが呼ばれるまでは重い処理のあるWakeUpクラスのインスタンスは生成されません。 public class WakeUpProxy : IWakeUp { private WakeUp _wakeUp; public WakeUpProxy() => Console.WriteLine($"{nameof(WakeUpProxy)}インスタンスが生成されました。"); public void WakeUpMorning() { _wakeUp ??= new WakeUp(); _wakeUp.WakeUpMorning(); } }
WakeUpProxyインスタンスが生成されました。 --- 朝 --- WakeUpインスタンスが生成されました。 眠いけど頑張って起きよう(´Д⊂ヽ
おわりに
なるほど、今回のサンプルコードですと朝を知らせる内容はProxyクラスから生成でき、朝起きる内容(重い処理)を出力させるときに対象のクラスを生成することが出来ました。 これをProxyパターンを用いずに実装すると朝を知らせる内容を出力したいときにまとめてインスタンス化する必要があるわけですね。 また一つ勉強になりました。しっかり身に着けていきたいと思います。