Javaにおけるプロキシパターン:スマートプロキシによるセキュリティと制御の強化
別名
- 代理
プロキシデザインパターンの意図
Javaにおけるプロキシパターンは、オブジェクトへのアクセスを効果的に制御するための代理またはプレースホルダーを提供し、セキュリティとリソース管理を強化します。
プロキシパターンの詳細な説明と実世界の例
実世界の例
実世界のシナリオでは、ゲート付きコミュニティの警備員を考えてみてください。警備員は住民のプロキシとして機能します。訪問者が到着すると、警備員は訪問者の資格と許可を確認してから、コミュニティへのアクセスを許可します。訪問者が承認されている場合、警備員は入場を許可します。そうでない場合は、入場は拒否されます。これにより、プロキシデザインパターンが特定のオブジェクトへのアクセスを制御するのと同様に、承認された個人のみがコミュニティにアクセスできるようになります。
平易な言葉で
Javaプロキシパターンを利用することで、クラスは別のクラスの機能をカプセル化し、アクセス制御と操作効率を合理化します。
Wikipediaによると
プロキシは、最も一般的な形式では、他のものへのインターフェースとして機能するクラスです。プロキシは、クライアントによって呼び出され、背後にある実際のサービスオブジェクトにアクセスするためのラッパーまたはエージェントオブジェクトです。プロキシの使用は、単に実際のオブジェクトへの転送である場合もあれば、追加のロジックを提供する場合もあります。プロキシでは、たとえば、実際のオブジェクトに対する操作がリソースを大量に消費する場合のキャッシングや、実際のオブジェクトに対する操作が呼び出される前に前提条件をチェックするなど、追加の機能を提供できます。
Javaにおけるプロキシパターンのプログラミング例
地元の魔法使いが呪文を研究するために行く塔を想像してください。象牙の塔には、最初の3人の魔法使いのみが入れるようにするプロキシを通してのみアクセスできます。ここで、プロキシは塔の機能を表現し、アクセス制御を追加します。
まず、WizardTower
インターフェースとIvoryTower
クラスがあります。
public interface WizardTower {
void enter(Wizard wizard);
}
@Slf4j
public class IvoryTower implements WizardTower {
public void enter(Wizard wizard) {
LOGGER.info("{} enters the tower.", wizard);
}
}
次に、単純なWizard
クラスがあります。
public class Wizard {
private final String name;
public Wizard(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
次に、WizardTower
にアクセス制御を追加するためのWizardTowerProxy
があります。
@Slf4j
public class WizardTowerProxy implements WizardTower {
private static final int NUM_WIZARDS_ALLOWED = 3;
private int numWizards;
private final WizardTower tower;
public WizardTowerProxy(WizardTower tower) {
this.tower = tower;
}
@Override
public void enter(Wizard wizard) {
if (numWizards < NUM_WIZARDS_ALLOWED) {
tower.enter(wizard);
numWizards++;
} else {
LOGGER.info("{} is not allowed to enter!", wizard);
}
}
}
そして、これが塔に入るシナリオです。
public static void main(String[] args) {
var proxy = new WizardTowerProxy(new IvoryTower());
proxy.enter(new Wizard("Red wizard"));
proxy.enter(new Wizard("White wizard"));
proxy.enter(new Wizard("Black wizard"));
proxy.enter(new Wizard("Green wizard"));
proxy.enter(new Wizard("Brown wizard"));
}
プログラム出力
08:42:06.183 [main] INFO com.iluwatar.proxy.IvoryTower -- Red wizard enters the tower.
08:42:06.186 [main] INFO com.iluwatar.proxy.IvoryTower -- White wizard enters the tower.
08:42:06.186 [main] INFO com.iluwatar.proxy.IvoryTower -- Black wizard enters the tower.
08:42:06.186 [main] INFO com.iluwatar.proxy.WizardTowerProxy -- Green wizard is not allowed to enter!
08:42:06.186 [main] INFO com.iluwatar.proxy.WizardTowerProxy -- Brown wizard is not allowed to enter!
Javaでプロキシパターンを使用するタイミング
プロキシは、単純なポインタよりもオブジェクトに対するより汎用性または洗練された参照が必要な場合に適用できます。プロキシパターンが適用可能な一般的な状況を以下に示します。一般的に、プロキシパターンは次の場合に使用されます。
- 別のオブジェクトへのアクセスを制御する
- 遅延初期化
- ロギングの実装
- ネットワーク接続を容易にする
- オブジェクトへの参照をカウントする
- 異なるアドレス空間にあるオブジェクトのローカル表現を提供する。
Javaにおけるプロキシパターンの実世界の応用例
- 仮想プロキシ:大きな画像や複雑な計算などの重いリソースが必要なアプリケーションでは、仮想プロキシを使用して、必要な場合にのみオブジェクトをインスタンス化できます。
- リモートプロキシ:リモートメソッド呼び出し(RMI)で、リモートオブジェクトとのやり取りを管理するために使用されます。
- 保護プロキシ:適切な承認を確保するために、元のオブジェクトへのアクセスを制御します。
- java.lang.reflect.Proxy
- Apache Commons Proxy
- モックフレームワーク Mockito,Powermock, EasyMock
- UIAppearance
プロキシパターンの利点とトレードオフ
利点
- アクセス制御:プロキシは実際のオブジェクトへのアクセスを制御し、チェック、ロギング、その他の操作を可能にします。
- 遅延初期化:プロキシは、リソースを大量に消費するオブジェクトの作成と初期化を、必要になるまで遅らせることができます。
- リモートプロキシ処理:ネットワーク通信を処理することにより、リモートオブジェクトとのやり取りを簡素化します。
トレードオフ
- オーバーヘッド:プロキシを追加すると、オーバーヘッドが増加する可能性のある追加レイヤーが導入されます。
- 複雑さ:クラスを追加することにより、システムの複雑さが増加します。
関連するJavaデザインパターン
- アダプター:アダプターパターンは既存のオブジェクトのインターフェースを変更しますが、プロキシは元のオブジェクトと同じインターフェースを提供します。
- アンバサダー:アンバサダーは、特にリモート通信において、アクセス制御と監視を強化する仲介役として機能するため、プロキシと似ています。
- デコレーター:デコレーターパターンとプロキシパターンの両方が間接性を提供しますが、デコレーターパターンはオブジェクトに動的に責任を追加する一方で、プロキシはアクセスを制御します。
- ファサード:ファサードは複雑なサブシステムへの簡略化されたインターフェースを提供しますが、プロキシは特定のオブジェクトへのアクセスを制御します。