前にも記事を書いたのですが、最近人に説明しよとうとしたら案外覚えてなかったのでどんなものか復習したのでアウトプットしてみました。
Proxyパターンとは?
GoFのデザインパターンに収録されているパターンの一つです。Proxyは「代理人」という意味を持ちます。ここで言う「代理人」は、実際に処理をする役割を持つ「RealSubject」の代わりに利用することが可能です。RealSubjectが必要になるまで生成を遅延できるというメリットがあります。
Proxyパターンの基本構造
- Subjectクラス → ProxyとRealSubJectに共通するインターフェースを規定します。
- Proxy → RealSubjectへのアクセスを代行するクラスです。
- RealSubject → 実際の処理を行うクラスです。
Proxyパターンを使ってみた
このまま上のクラス図をそのままコードに落とすと全く面白くないので、「メッセージを送信」にProxyパターンを適用してみたいと思います。
簡単な仕様
- メッセージはデフォルトではどこにも送信しない。
- RealSubjectに相当する部分でメッセージを送信する機能を持たせる。
- クライアントはRealSubjectが必要になるタイミングを知っている
技術的なメモ:
- 利用者はRealProxyに当たるオブジェトの存在や生成タイミングは知らない。
- Peoxyに相当するオブジェクトはメッセージを送信する際にRealSubjectに相当するオブジェクトを生成する。
- RealSubjectはオブジェクト生成にコストがかかる。
制作予定のクラス図
Proxyパターンソースコード (c#)
Main (Client相当)
public class AppMain { public static void Main() { ISendable s = new MessagingProxy(); s.Address = "128.0.0.2"; s.SendMessage("Yes!!"); } }
ISendable (Subject相当)
public interface ISubject { string Address { get; set; } void SendMessage(string message); }
MessagingProxy (Proxy相当)
public class MessagingProxy : ISendable { private ISendable real; // RealSubjectを格納するための変数 // 送信先アドレス public string Address { get; set; } // コンストラクタ public MessagingProxy { } // メッセージの送信 public void SendMessage(string message) { if(this.real == null) { this.real = new RealMessaging(); } this.real.Address = this.Address; // プロパティの移し替え this.real.SendMessage(message); } }
RealMessaging (RealSubject相当)
public class RealMessaging : ISendable { // 送信先アドレス public string Address { get; set; } // コンストラクタ public RealMessaging { Thread.Sleep(5 * 1000 /* 5sec */); // 時間がかかる様子を表現 } // メッセージの送信 public void SendMessage(string message) { // Addressで指定されたエンドポイントにメッセージを送信 } }
補足:
オブジェクトの生成にコストがかかるという例えをコンストラクタの呼び出しに時間がかかるように表現しましたが、イニシャライズのメソッドに時間がかかるものでも同じかと思います。
まとめ
必要になったらインスタンスを生成しますが、利用者からはそんな事は関係なく利用できますね。特に画像、ネットワーク、遠隔地のデータベースなどの操作を隠蔽するのに向いているかと思います。