プロキシデザインパターンUMLダイアグラム:
Javaプロキシデザインパターン - 静的エージェント
この例は非常に単純な、一方向のみのあるwirteCode
インタフェースIDeveloper
:
public interface IDeveloper {
public void writeCode();
}
// 实现这个接口的类:
public class Developer implements IDeveloper{
private String name;
public Developer(String name){
this.name = name;
}
@Override
public void writeCode() {
System.out.println("Developer " + name + " writes code");
}
}
テストコード:
public class DeveloperTest {
public static void main(String[] args) {
IDeveloper jerry = new Developer("Jerry");
jerry.writeCode();
}
}
テスト出力:
Developer Jerry writes code
トラブルは今、ジェリーのような開発者としてジェリーのリーダーシップチームは、それが満たされていない、技術文書を書いていないので、ということです。議論の後、チームが関連するドキュメントは、コードで提供されなければならない合意に達しました。
変更され、既存の実装クラスの開発者に直接書き込むために、開発者を強制することなく、文書に、あなたは今達成するために、静的なプロキシを使用することができます。
// 创建一个和Developer类实现同样接口的类
public class DeveloperProxy implements IDeveloper{
private IDeveloper developer;
// 引用Developer类对象
public DeveloperProxy(IDeveloper developer){
this.developer = developer;
}
@Override
public void writeCode() {
System.out.println("Write documentation...");
this.developer.writeCode();
}
}
テストコード:
public class DeveloperTest {
public static void main(String[] args) {
Developer jerry = new Developer("jerry");
DeveloperProxy jerryproxy = new DeveloperProxy(jerry);
jerryproxy.writeCode();
}
}
テスト出力:
Write documentation...
Developer jerry writes code
帯電防止剤の利点
安定性を達成するために、既存のコードの元のクラスを変更することなく、あなたがプロキシクラスを作成し、私有財産の代理として、元のパッケージを実現することができ、あなたが強化したいとします。プロキシクラスで強化された機能が実行され、既存のコードは完全に透過的です。上記の例に戻ると、クライアントコードは、呼び出すために、それを気にしないwriteCode()
本当の開発者や開発者のコードに変数ポイントの方法を。
利点:
- 実装し、理解しやすいです
- その薬のオリジナルの実装との間の関係は、コンパイル時、追加の実行時のオーバーヘッドで決定されています。
帯電防止剤の欠点
我々はまだ説明するために、この例を使用します。
行方不明の文書の問題がまだQAの同僚に存在することになりましたと。私たちは、静的なエージェントを介してこの問題を解決したい場合は、エージェントは別のクラスを導入しなければなりません。
これは、インターフェーステスターです。
public interface ITester {
public void doTesting();
}
// ITester 接口的实现类:
public class Tester implements ITester {
private String name;
public Tester(String name){
this.name = name;
}
@Override
public void doTesting() {
System.out.println("Tester " + name + " is testing code");
}
}
テスターエージェント:
public class TesterProxy implements ITester{
private ITester tester;
public TesterProxy(ITester tester){
this.tester = tester;
}
@Override
public void doTesting() {
System.out.println("Tester is preparing test documentation...");
tester.doTesting();
}
}
出力とテストコード:
ソースコードからテスターエージェント、我々は簡単にそれが同じロジックを持つ開発者であることがわかります。一定期間の後、我々はプロセスで文書配信ソフトウェア他の同僚を確立する必要がある場合、我々は再び非常に大きくなり、静的なプロキシクラスにつながることができ、新たな静的プロキシクラスの時間を、導入しなければなりません。
Javaで動的プロキシ - 呼処理
今、私のプロキシクラスを介してEnginnerProxy
、元の実装クラスごとに個別にではなく、専用の静的プロキシクラスよりも、特定の役割のすべてに代理店サービスを提供します。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class EnginnerProxy implements InvocationHandler
{
Object obj;
public Object bind(Object obj)
{
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
System.out.println("Enginner writes document");
Object res = method.invoke(obj, args);
return res;
}
}
主な注意事項:
- JDK剤によって提供されるインタフェースの継承技術から、サービス・インターフェース(IDeveloper又はITester)を有する専用のインターフェースから継承されたが、この変形例ではありません
InvocationHandler
。 - エージェントはプロキシで定義されている一般的なタイプの持つ、すべての一般的な可能な実装クラスに適用することができることを確実にするために、
Object
変数を。 - プロキシインスタンスのメソッド呼び出しインターフェースは、それがされたとき
InvocationHandler
に定義されているinvoke
人物が強調ロジックにより、アプリケーション開発者によって宣言されるインターセプト法、Java Reflection
元のコール・ロジックとの呼。
ここでは、動的プロキシのInvocationHandlerの設計とテスト出力を使用する方法は次のとおりです。
動的プロキシクラスを制限
帯電防止剤の成功のこの変異体は欠陥を繰り返すことを避けるために、それは依然として限界があるが、動的プロキシクラスの使用は、クラスが最初のオリジナルまたは実装しなければならない、すなわち、インターフェースの実装クラスから継承されていない使用することができません複数のインターフェースは、このインターフェースは、エージェントのインタフェースです。
次の例を考え、製品の所有者は、任意のインタフェースを実装していません。
public class ProductOwner {
private String name;
public ProductOwner(String name){
this.name = name;
}
public void defineBackLog(){
System.out.println("PO: " + name + " defines Backlog.");
}
}
次のコードは、IDEには構文エラーがありません。
ProductOwner po = new ProductOwner("Ross");
ProductOwner poProxy = (ProductOwner) new EnginnerProxy().bind(po);
poProxy.defineBackLog();
残念ながら、タイムズ紙は、次のエラーをコンパイル: