コンピュータプログラミングにおいて、プロキシパターンとは、他のオブジェクトへのインターフェースとして機能するクラスのソフトウェア設計パターンです。プロキシは、ネットワーク接続、メモリ内の大きなオブジェクト、ファイル、あるいは複製が困難または不可能なその他のリソースなど、あらゆるものとインターフェースできます。つまり、プロキシは、クライアントが呼び出して、舞台裏で実際のサービスオブジェクトにアクセスするためのラッパーまたはエージェントオブジェクトです。プロキシの使用は、単に実際のオブジェクトに転送するだけでなく、追加のロジックを提供することもできます。プロキシでは、たとえば、実際のオブジェクトに対する操作がリソースを大量に消費する場合にキャッシュしたり、実際のオブジェクトに対する操作が呼び出される前に前提条件をチェックしたりするなど、追加機能を提供できます。クライアントにとって、プロキシオブジェクトの使用方法は、実際のオブジェクトの使用方法と似ています。なぜなら、どちらも同じインターフェースを実装しているからです。
プロキシ設計パターンは、柔軟で再利用可能なオブジェクト指向ソフトウェア、つまり実装、変更、テスト、再利用が容易なオブジェクトを設計するために、繰り返し発生する設計上の問題を解決する方法を記述した、23のよく知られたGoF設計パターンの1つです。[ 1 ]
プロキシ設計パターンは、このような問題を解決するために使用されます。[ 2 ]
例えば、機密性の高いオブジェクトにアクセスする場合、クライアントが必要なアクセス権限を持っているかどうかを確認できる必要がある。
別個のProxyオブジェクトを定義します
Subject。Proxyこれにより、オブジェクトを介して操作を行い、対象にアクセスする際に、機密性の高いオブジェクトにアクセスするクライアントのアクセス権限を確認するなど、追加機能を実行することが可能になります。
主体の代わりとして機能するには、プロキシはSubjectインターフェースを実装する必要があります。クライアントは、自分が主体とやり取りしているのか、それともそのプロキシとやり取りしているのかを区別できません。
下記のUMLクラス図およびシーケンス図も参照してください。

上記のUMLクラス図では、Proxyクラスはインターフェースを実装してオブジェクトSubjectの代替として機能します。代替オブジェクト ( ) へのSubject参照 ( ) を保持し、リクエストをそのオブジェクト ( ) に転送します。realSubjectRealSubjectrealSubject.operation()
シーケンス図は実行時の相互作用を示しています。オブジェクトは、オブジェクトへのアクセスを制御するオブジェクトClientを介して動作します。この例では、リクエストがに転送され、リクエストが実行されます。ProxyRealSubjectProxyRealSubject


分散オブジェクト通信では、ローカルオブジェクトはリモートオブジェクト(異なるアドレス空間に属するオブジェクト)を表します。ローカルオブジェクトはリモートオブジェクトのプロキシとして機能し、ローカルオブジェクトに対するメソッド呼び出しは、リモートオブジェクトに対するリモートメソッド呼び出しにつながります。例としては、ATMの実装が挙げられます。ATMは、リモートサーバーに存在する銀行情報のプロキシオブジェクトを保持する場合があります。
複雑なオブジェクトや重いオブジェクトの代わりに、スケルトン表現が有利な場合もあります。基となる画像が非常に大きい場合は、仮想プロキシオブジェクトを使用して表現し、必要に応じて実際のオブジェクトを読み込むことができます。
保護プロキシは、アクセス権限に基づいてリソースへのアクセスを制御するために使用される場合があります。
以下は、 C++におけるプロキシ設計パターンの例です。
import std ;using std :: string ; using std :: unique_ptr ;// サブジェクトインターフェースclass Image { public : virtual void display () const = 0 ; virtual ~ Image () = default ; };// 実際の被写体 (読み込みにコストがかかる) class RealImage : public Image { private : string filename ; public : explicit RealImage ( const string & file ) : filename { file } { loadFromDisk (); }void display () const override { std :: println ( "画像を表示しています: {}" , filename ); }private : void loadFromDisk () const { std :: println ( "ディスクからイメージを読み込んでいます: {}" , filename ); } };// プロキシ (RealImage へのアクセスを制御) class ProxyImage : public Image { private : string filename ; mutable unique_ptr < RealImage > realImage ; // 遅延作成public : explicit ProxyImage ( const string & file ) : filename { file } {}void display () const override { if ( ! realImage ) { std :: println ( "(プロキシ) オンデマンドで画像を読み込んでいます..." ); realImage = std :: make_unique <RealImage> ( filename ); } realImage- > display () ; } } ;// クライアントコードint main () { Image * img = new ProxyImage ( "photo.png" );// 最初の表示(ロードされるはず)img -> display ();// 2番目のディスプレイ(キャッシュされた画像を使用)img -> display ();画像を削除; 0を返す; }