JAVA デザイン パターン 6: プロキシ パターン。ターゲット オブジェクトへのアクセスを制御するために使用されます。

著者のホームページ:デザイナー Xiao Zheng
著者について: JAVA テクノロジー、システム カスタマイズ、リモート ガイダンスに重点を置いた 3 年間の JAVA フルスタック開発経験、エンタープライズ デジタル トランスフォーメーションに注力、CSDN ブログ エキスパート、Alibaba Cloud コミュニティ エキスパート ブロガー、Blue Bridge クラウドコースの講師。

ここに画像の説明を挿入します


1. 代理店モデルとは何ですか?

プロキシ パターンは、ターゲット オブジェクトへのアクセスを制御するプロキシ オブジェクトを提供する、一般的に使用される設計パターンです

プロキシ モードでは、プロキシ オブジェクトはターゲット オブジェクトの中間層として機能し、クライアントはプロキシ オブジェクトを通じてターゲット オブジェクトと対話します。

Java では、プロキシ モードは静的プロキシと動的プロキシの 2 つの形式に分類できます。簡単に理解してください。

  1. 静的プロキシ\color{red}{静的プロキシ}静的プロキシ: 静的プロキシでは、プロキシ クラスとターゲット クラスの両方が同じインターフェイスを実装するか、同じ親クラスを継承する必要があります。プロキシ クラスはターゲット オブジェクトへの参照を保持し、ターゲット オブジェクトのメソッドを呼び出す前または後に追加の操作を実行します。静的プロキシはシンプルで分かりやすいというメリットがありますが、対象クラスごとにプロキシクラスを記述する必要があり、対象クラスが多い場合にはメンテナンスが大変になるというデメリットがあります。
  2. 動的プロキシ\color{red}{動的プロキシ}動的プロキシ: 動的プロキシは実行時にプロキシ クラスを動的に生成するため、ターゲット クラスごとにプロキシ クラスを記述する必要がありません。Java は 2 つの動的プロキシ メソッドを提供します。1 つはインターフェイスベースの動的プロキシ (JDK 動的プロキシ)、もう 1 つはクラスベースの動的プロキシ (CGLIB 動的プロキシ) です。JDK ダイナミック プロキシでは、ターゲット オブジェクトがインターフェイスを実装する必要があり、実行時にリフレクション メカニズムを通じてプロキシ クラスを作成します。プロキシ クラスは、ターゲット インターフェイスを実装し、ターゲット オブジェクトへの参照を保持します。CGLIB ダイナミック プロキシは、ターゲット クラスを継承してプロキシ クラスを作成し、プロキシ クラスはターゲット オブジェクトへの参照を保持します。動的プロキシの利点は、柔軟性が高く、あらゆる種類のオブジェクトをプロキシできることですが、欠点は、静的プロキシよりも若干複雑であることです。

プロキシ モードの主な適用シナリオは次のとおりです。4 44種類。

  • リモート エージェント\color{red}{リモート エージェント}リモート プロキシ: リモート オブジェクトにローカル インターフェイスを提供し、ネットワーク通信の複雑さを隠します。
  • 仮想エージェント\color{red}{仮想エージェント}仮想プロキシ: 必要に応じて高価なオブジェクトを作成し、オブジェクトのインスタンス化を遅らせます。
  • セキュリティ エージェント\color{red}{セキュリティ エージェント}セキュリティ エージェント: ターゲット オブジェクトへのアクセスを制御します。
  • インテリジェント エージェント\color{red}{インテリジェント エージェント}インテリジェント エージェント: ロギング、パフォーマンス監視など、ターゲット オブジェクトにアクセスする際の追加のロジック処理を追加します。

プロキシモードにより、対象オブジェクトの制御や強化が可能となり、システムの柔軟性や保守性が向上します。

ここに画像の説明を挿入します


2. プロキシモードの例

以下は、静的プロキシと動的プロキシの実装を示す Java プロキシ モードの簡単なサンプル コードですので、ローカル実行にコピーしてください。

2.1 静的プロキシ

// 定义接口
interface Subject {
    
    
    void doSomething();
}

// 定义目标类
 RealSubject implements Subject {
    
    
    @Override
    public void doSomething() {
    
    
        System.out.println("RealSubject doSomething");
    }
}

// 定义代理类
class ProxySubject implements Subject {
    
    
    private RealSubject realSubject;

    public ProxySubject(RealSubject realSubject) {
    
    
        this.realSubject = realSubject;
    }

    @Override
 public void doSomething() {
    
    
        System.out.println("Before doSomething");
        realSubject.doSomething();
        System.out.println("After doSomething");
    }
}

// 使用示例
public class ProxyPatternExample {
    
    
    public static void main(String[] args) {
    
    
        RealSubject realSubject = new RealSubject();
        ProxySubject proxySubject = new ProxySubject(realSubject        proxySubject.doSomething();
    }
}

2.2 動的プロキシ

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 定义接口
interface Subject {
    
    
    void doSomething();
}

// 定义目标类
 RealSubject implements Subject {
    
    
    @Override
    public void doSomething() {
    
    
        System.out.println("RealSubject doSomething");
    }
}

// 定义代理处理器
class ProxyHandler implements InvocationHandler {
    
    
    private Object target;

    public ProxyHandler(Object target) {
    
    
        this.target = target;
    }

    @Override
    public Object invoke(Object, Method method, Object[] args) throws Throwable {
    
    
        System.out.println("Before " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("After " + method.getName());
        return result;
    }
}

// 使用示例
public class ProxyPatternExample {
    
    
    public static void main(String[] args) {
    
    
        RealSubjectSubject = new RealSubject();
        ProxyHandler handler = new ProxyHandler(realSubject);

        Subject proxySubject = (Subject) Proxy.newProxyInstance(
                realSubject.getClass().getClassLoader(),
                realSubject.getClass().getInterfaces(),
                handler);

        proxySubject.doSomething();
    }
}

上記のコードは、静的プロキシと動的プロキシの実装を示しています。

静的プロキシではターゲット クラスごとにプロキシ クラスを作成する必要がありますが、動的プロキシではリフレクション メカニズムを通じて実行時にプロキシ オブジェクトが動的に生成されます。

プロキシ オブジェクトを通じて、ターゲット オブジェクトのメソッドを呼び出す前または呼び出した後に追加のロジックを実行できます。

ここに画像の説明を挿入します


3. エージェントモードの適用シナリオ

Java プロキシ モードには多くのアプリケーション シナリオがあります。次に挙げるのは6 6です。6 つの一般的なアプリケーション シナリオをよく読んでください。

  1. リモートプロキシ: リモート API 呼び出し、リモート サービス呼び出しなど、プロキシ経由でリモート オブジェクトにアクセスします。プロキシ オブジェクトは、ネットワーク通信と複雑さを隠し、シンプルなローカル インターフェイスを提供します。
  2. 仮想プロキシ: 実際のオブジェクトにアクセスする前に、プロキシ オブジェクトを使用してオブジェクトのインスタンス化を遅らせます。たとえば、大きなリソース (写真、ビデオなど) を読み込む場合、最初に仮想プロキシを使用してプレースホルダを表示できます。画像またはプロンプト情報。実際のオブジェクトにアクセスする必要がある場合にインスタンス化します。
  3. セキュリティプロキシ: プロキシ オブジェクトを介して、ID 認証、権限チェックなど、ターゲット オブジェクトへのアクセスを制御します。ターゲット オブジェクトにアクセスする前に、プロキシ オブジェクトはセキュリティ チェックを実行して、正当なユーザーのみがアクセスできることを確認できます。
  4. キャッシュプロキシ: ターゲット オブジェクトのキャッシュ メカニズムを提供します。たとえば、データベースへのアクセスや他の時間のかかる操作の前に、プロキシ オブジェクトはまず、対応する結果がキャッシュに存在するかどうかを確認できます。存在する場合は、キャッシュされた結果を直接返します。データを削除し、実際のオブジェクトへのアクセス回数を減らします。
  5. ロギングプロキシ: メソッドの入力パラメータ、出力パラメータ、時間のかかる情報、その他の情報を記録するなど、プロキシ オブジェクトを通じてシステム コール ログを記録し、その後の分析やトラブルシューティングを容易にします。
  6. パフォーマンス監視プロキシ: パフォーマンスの最適化と監視のために、メソッドの実行時間、呼び出し数、その他の情報を記録するなど、プロキシ オブジェクトを通じてターゲット オブジェクトのパフォーマンスを監視します。

上記は一般的なアプリケーション シナリオの一部にすぎませんが、実際、プロキシ モードは非常に柔軟で、特定のニーズに応じて拡張および適用できます。

プロキシパターンを利用することで、対象オブジェクトを変更することなく、対象オブジェクトの動作を制御・強化することができ、システムの柔軟性や保守性が向上します。

ここに画像の説明を挿入します


4. エージェントモデルの面接での質問

  1. プロキシ パターンとは何かを説明し、その適用シナリオの例を示してください。
  2. 静的プロキシと動的プロキシの違いを比較してください。
  3. Javaで静的プロキシを実装するにはどうすればよいですか? サンプルコードを教えてください。
  4. Javaで動的プロキシを実装するにはどうすればよいですか? サンプルコードを教えてください。
  5. JDKダイナミックプロキシとは何ですか? どのように機能するのでしょうか?
  6. CGLIB 動的プロキシとは何ですか? どのように機能するのでしょうか?
  7. 代理店モデルの長所と短所は何ですか?
  8. プロキシパターンにおいて、プロキシクラスとターゲットクラスとは何ですか?
  9. プロキシ パターンとデコレータ パターンの違いは何ですか?
  10. プロキシ パターンに加えて、同様の機能を実現するために他のどのような設計パターンを使用できますか?

ここに画像の説明を挿入します

おすすめ

転載: blog.csdn.net/qq_41464123/article/details/132838945