プロキシ設計パターン

DDD
DDDオリジナル
2024-10-19 12:36:01408ブラウズ

Proxy Design Pattern

以前のブログでは、オブジェクト作成メカニズムを扱うさまざまな作成デザイン パターンを検討しました。ここで、構造設計パターンについて詳しく見ていきましょう。これは、オブジェクトとクラスを柔軟かつ効率的に保ちながら、より大きな構造を形成する方法に焦点を当てています。プロキシ設計パターンから始めましょう

JavaScript のプロキシ設計パターン

プロキシ デザイン パターンは、別のオブジェクトを表すオブジェクトを提供する構造的なデザイン パターンです。これは、実際のオブジェクトへのアクセスを制御する仲介者として機能し、元のオブジェクトのコードを変更せずに、遅延初期化、ロギング、アクセス制御、キャッシュなどの追加の動作を追加します。

JavaScript では、プロキシは Proxy オブジェクトによって提供される組み込み機能であり、プロパティ アクセス、割り当て、関数呼び出しなどの基本的な操作のカスタム動作を定義できます。

プロキシ パターンが必要になるのはどのような場合ですか?

プロキシ パターンは、次の場合に特に役立ちます。

  • 遅延初期化: リソースを大量に使用するオブジェクトの作成を、必要になるまで遅らせたいとします。
  • アクセス制御: たとえば、無許可のアクセスを制限したり、条件に基づいて操作を制限したりするために、オブジェクトへのアクセスを制御する必要があります。
  • ログ: オブジェクトに対するアクション (プロパティ アクセスやメソッド呼び出しなど) をログに記録します。
  • キャッシュ: 冗長な計算を避けるために、負荷の高い操作の結果をキャッシュしたいとします。

プロキシ パターンのコンポーネント

  1. 件名: 実際のオブジェクトとプロキシの両方に共通の操作を定義するインターフェイス。
  2. RealSubject: 実際の作業を実行する実際のオブジェクト。
  3. プロキシ: RealSubject へのアクセスを制御する仲介者。

類推:

ゲストに見せたい大きな絵画があると想像してください。しかし、それを倉庫から取り出すのに時間がかかります (重くて運ぶのに時間がかかるため)。毎回それを待つのではなく、実際の絵が取りに来るのを待っている間に、絵の小さなポストカード画像を使用してすぐに見せることにしました。

このたとえでは:

  • 大きな絵は実際のオブジェクトです (読み込みに時間がかかる画像など)。
  • ポストカードは代理です (実際のオブジェクトの準備ができるまでの代わりとなる軽量の代替品)。
  • 実際の絵画の準備ができたら、実際の絵画をゲストに見せます。

現実世界の例え:

不動産業者を代理人と考えてください。家を購入したいと思ったとき、すぐにすべての家を訪問する(実物を積み込む)わけではありません。代わりに、不動産業者(代理人)が最初に写真と説明を見せます。購入する準備ができたとき (つまり、display() を呼び出したとき) にのみ、エージェントが自宅訪問を手配します (実際のオブジェクトをロードします)。

実際の例: 画像の読み込み (仮想プロキシ)

ユーザーが要求するまで画像の読み込みを遅らせる (遅延読み込み) 必要がある、Web アプリケーションでの画像読み込みの例を使用してみましょう。プロキシは、実際のイメージがロードされるまでプレースホルダーとして機能します。

ここでは、JavaScript でプロキシ設計パターンを実装する方法を説明します。

例: 画像ロードのプロキシ

// Step 1: The real object
class RealImage {
  constructor(filename) {
    this.filename = filename;
    this.loadImageFromDisk();
  }

  loadImageFromDisk() {
    console.log(`Loading ${this.filename} from disk...`);
  }

  display() {
    console.log(`Displaying ${this.filename}`);
  }
}

// Step 2: The proxy object
class ProxyImage {
  constructor(filename) {
    this.realImage = null; // no real image yet
    this.filename = filename;
  }

  display() {
    if (this.realImage === null) {
      // load the real image only when needed
      this.realImage = new RealImage(this.filename);
    }
    this.realImage.display(); // display the real image
  }
}

// Step 3: Using the proxy to display the image
const image = new ProxyImage("photo.jpg");
image.display(); // Loads and displays the image
image.display(); // Just displays the image (already loaded)

説明:

1)。実像:

  • RealImage クラスは実際のイメージを表します。
  • 入力としてファイル名を受け取り、ディスクからイメージをロードする時間のかかるプロセス (loadImageFromDisk メソッドで示される) をシミュレートします。
  • ロードされると、display メソッドを使用して画像が表示されます。

2)。プロキシ画像:

  • ProxyImage クラスは、RealImage の代わりとして機能します。実際のイメージはすぐにはロードされません。
  • 実際のイメージへの参照を保持します (ただし、実際のイメージはまだロードされていないため、最初は null です)。
  • プロキシ上で display メソッドを呼び出すと、実際のイメージがロードされているかどうかがチェックされます。そうでない場合は、最初にロードしてから表示します。

3)。使用法:

  • ProxyImage のインスタンスを作成するとき、実際のイメージはまだロードされていません (リソースを大量に消費するため)。
  • 最初に display が呼び出されるとき、プロキシは (RealImage クラスを使用して) 画像をロードし、それを表示します。
  • 2 回目の表示呼び出しでは、実際の画像は既にロードされているため、再度ロードせずに画像のみを表示します。

組み込みの Proxy オブジェクト

ES6 プロキシは、ターゲットとハンドラーを引数として受け入れるプロキシ コンストラクターで構成されています

const proxy = new Proxy(target, handler)

ここで、ターゲットはプロキシが適用されるオブジェクトを表し、ハンドラーはプロキシの動作を定義する特別なオブジェクトです。

ハンドラー オブジェクトには、トラップ メソッド (apply、get、set、has など) と呼ばれる事前定義された名前を持つ一連のオプションのメソッドが含まれています。これらのメソッドは、対応する操作がプロキシ インスタンスで実行されるときに自動的に呼び出されます。

組み込みプロキシを使用して計算機を実装してこれを理解しましょう

// Step 1: The real object
class RealImage {
  constructor(filename) {
    this.filename = filename;
    this.loadImageFromDisk();
  }

  loadImageFromDisk() {
    console.log(`Loading ${this.filename} from disk...`);
  }

  display() {
    console.log(`Displaying ${this.filename}`);
  }
}

// Step 2: The proxy object
class ProxyImage {
  constructor(filename) {
    this.realImage = null; // no real image yet
    this.filename = filename;
  }

  display() {
    if (this.realImage === null) {
      // load the real image only when needed
      this.realImage = new RealImage(this.filename);
    }
    this.realImage.display(); // display the real image
  }
}

// Step 3: Using the proxy to display the image
const image = new ProxyImage("photo.jpg");
image.display(); // Loads and displays the image
image.display(); // Just displays the image (already loaded)

この方法でプロキシを使用する最良の部分:

  • プロキシ オブジェクトは、元の Calculator クラスのプロトタイプを継承します。
  • 突然変異は、プロキシの設定されたトラップによって回避されます。

コードの説明

1)。 プロトタイプの継承:

  • プロキシは **Calculator **クラスの元のプロトタイプに干渉しません。
  • これは、proxiedCalculator.proto === Calculator.prototype かどうかをチェックすることで確認されます。結果は true になります。

2)。 getOperations の処理:

  • get トラップは、プロキシ オブジェクトのプロパティ アクセスをインターセプトします。
  • 元のオブジェクトのプロパティとメソッドに安全にアクセスするには、Reflect.get を使用します。

3)。 突然変異の防止:

設定されたトラップは、ターゲット オブジェクトのプロパティを変更しようとするたびにエラーをスローします。これにより不変性が保証されます。

4)。 プロキシを介したプロトタイプ メソッドの使用:

プロキシを使用すると、元のオブジェクトのプロトタイプで定義されている加算、減算、乗算、除算などのメソッドにアクセスできます。

ここで観察すべき重要なポイントは次のとおりです:

  • プロトタイプの継承を維持します: プロキシはすべてのプロトタイプ メソッドへのアクセスを保持し、元の電卓と同様に動作します。
  • 突然変異の防止: 設定されたトラップにより、電卓オブジェクトの内部状態が予期せず変更されないことが保証されます。
  • プロパティとメソッドへの安全なアクセス: get トラップにより、有効なプロパティのみがアクセスされることが保証され、堅牢性が向上します。

ここまで進んだ場合は、忘れずに「いいね!」を押して、質問や意見があれば下にコメントを残してください。あなたのフィードバックは私にとってとても大切なものです。ぜひご意見をお待ちしております!

以上がプロキシ設計パターンの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。