Proxy パターン
Proxy パターンは、プログラミングにおけるデザインパターンの一種。Proxy(プロキシ、代理人)とは、大まかに言えば、別物のインタフェースとして機能するクラスである。その「別物」は何でもよく、ネットワーク接続だったり、メモリ上の大きなオブジェクトだったり、複製がコスト高あるいは不可能な何らかのリソースなどである。
Proxy パターンのよく知られている例として、参照カウント付きポインタオブジェクトがある。
複雑なオブジェクトの複数のコピーが必須となる状況では、Proxy パターンに Flyweight パターンを加えることでメモリ使用量を抑えることができる。通常、複雑なオブジェクトのインスタンスは1つだけ生成し、プロキシオブジェクトを複数生成する。それらプロキシオブジェクトは唯一の複雑なオブジェクトへの参照を含む。プロキシへの操作は、オリジナルのオブジェクトにフォワードされる。プロキシオブジェクトが全て破棄されると、参照されていた複雑なオブジェクトの使用していたメモリも解放される。
例
[編集 ]Virtual Proxy (Java)
[編集 ]以下のJavaの例は、"virtual proxy" パターンを示したものである。このプログラムは以下のように出力する。
Loading HiRes_10MB_Photo1 Displaying HiRes_10MB_Photo1 Loading HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo2
ProxyImage
クラスは、実際に必要になるまで時間のかかる画像ファイルのロードを遅延させる。ファイルが結局必要とされなかった場合、時間のかかるロードは全く行われずに済む。
importjava.util.*; interface Image{ publicvoiddisplayImage(); } class RealImageimplementsImage{ privateStringfilename; publicRealImage(Stringfilename){ this.filename=filename; loadImageFromDisk(); } privatevoidloadImageFromDisk(){ // 時間のかかる一連の操作 // ... System.out.println("Loading "+filename); } publicvoiddisplayImage(){System.out.println("Displaying "+filename);} } class ProxyImageimplementsImage{ privateStringfilename; privateImageimage; publicProxyImage(Stringfilename){this.filename=filename;} publicvoiddisplayImage(){ if(image==null){ image=newRealImage(filename);// ロードはオンデマンドでのみ行われる } image.displayImage(); } } class ProxyExample{ publicstaticvoidmain(String[]args){ Imageimage1=newProxyImage("HiRes_10MB_Photo1"); Imageimage2=newProxyImage("HiRes_10MB_Photo2"); Imageimage3=newProxyImage("HiRes_10MB_Photo3"); image1.displayImage();// ロードが必要 image2.displayImage();// ロードが必要 image2.displayImage();// すでにロード済みなのでロード不要 // image3の画像は一度もロードされない } }
Protection Proxy (C#)
[編集 ]以下のC#の例では、RealClient
はアカウント番号を格納する。正しいパスワードを知っているユーザーだけが、このアカウント番号にアクセスできる。RealClient
はパスワードを知っている ProtectionProxy
で守られている。ユーザーがアカウント番号を得たい場合、まずプロキシがユーザーに対して認証を求め、ユーザーが正しいパスワードを入力したときだけプロキシが RealClient
を呼び出してアカウント番号をユーザーに通知する。
この例では、正しいパスワードは thePassword である。
usingSystem; namespaceConsoleApplicationTest.FundamentalPatterns.ProtectionProxyPattern { publicinterfaceIClient{ stringGetAccountNo(); } publicclassRealClient:IClient{ privatestringaccountNo="12345"; publicRealClient(){ Console.WriteLine("RealClient: Initialized"); } publicstringGetAccountNo(){ Console.WriteLine("RealClient's AccountNo: "+accountNo); returnaccountNo; } } publicclassProtectionProxy:IClient { privatestringpassword;//秘密のパスワード RealClientclient; publicProtectionProxy(stringpwd){ Console.WriteLine("ProtectionProxy: Initialized"); password=pwd; client=newRealClient(); } // ユーザーを認証し、アカウント番号を返す publicStringGetAccountNo(){ Console.Write("Password: "); stringtmpPwd=Console.ReadLine(); if(tmpPwd==password){ returnclient.GetAccountNo(); }else{ Console.WriteLine("ProtectionProxy: Illegal password!"); return""; } } } classProtectionProxyExample { [STAThread] publicstaticvoidMain(string[]args){ IClientclient=newProtectionProxy("thePassword"); Console.WriteLine(); Console.WriteLine("main received: "+client.GetAccountNo()); Console.WriteLine("\nPress any key to continue . . ."); Console.Read(); } } }
関連項目
[編集 ]外部リンク
[編集 ]- Proxy pattern in Java
- Proxy pattern in UML and in LePUS3 (a formal modelling language)
- Jt J2EE Pattern Oriented Framework
- Compositeパターン/Proxyパターン ITpro、矢沢久雄
GoFによる23種のパターン |
| ||||||
---|---|---|---|---|---|---|---|
並行性に関するパターン | |||||||
アーキテクチャに関するパターン | |||||||
その他のパターン |
| ||||||
関連する人々 | |||||||
関連項目 | |||||||