以前のブログでは、オブジェクト作成メカニズムを扱うさまざまな作成デザイン パターンを検討しました。ここで、構造設計パターンについて詳しく見ていきましょう。オブジェクトとクラスを柔軟かつ効率的に保ちながら、より大きな構造を形成するためにどのように構成されるかに焦点を当てます。プロキシ設計パターンから始めましょう
プロキシ デザイン パターンは、別のオブジェクトを表すオブジェクトを提供する構造的なデザイン パターンです。これは、実際のオブジェクトへのアクセスを制御する仲介者として機能し、元のオブジェクトのコードを変更することなく、遅延初期化、ロギング、アクセス制御、キャッシュなどの追加動作を追加します。
JavaScript では、プロキシは Proxy オブジェクトによって提供される組み込み機能であり、プロパティ アクセス、割り当て、関数呼び出しなどの基本的な操作のカスタム動作を定義できます。
プロキシ パターンは、次の場合に特に役立ちます。
ゲストに見せたい大きな絵画があるが、倉庫から取り出すのに時間がかかると想像してください (重くて運ぶのに時間がかかるため)。毎回それを待つのではなく、実際の絵が取り込まれるのを待っている間に、絵の小さなポストカード画像を使用してすぐに見せることにしました。
この例えでは:
不動産業者は代理店だと考えてください。家を購入したいと思ったとき、すぐにすべての家を訪問する(実物を積み込む)わけではありません。代わりに、不動産業者(代理人)が最初に写真と説明を見せます。購入する準備ができたとき (つまり、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)。実像:
2)。プロキシ画像:
3)。使用法:
ES6 プロキシは、ターゲットとハンドラーを引数として受け入れるプロキシ コンストラクターで構成されています
const proxy = new Proxy(target, handler)
ここで、ターゲットはプロキシが適用されるオブジェクトを表し、ハンドラーはプロキシの動作を定義する特別なオブジェクトです。
ハンドラー オブジェクトには、トラップ メソッド (apply、get、set、has など) と呼ばれる事前定義された名前を持つ一連のオプションのメソッドが含まれています。これらのメソッドは、対応する操作がプロキシ インスタンスで実行されるときに自動的に呼び出されます。
組み込みプロキシを使用して電卓を実装してこれを理解しましょう
// Step 1: Define the Calculator class with prototype methods class Calculator { constructor() { this.result = 0; } // Prototype method to add numbers add(a, b) { this.result = a b; return this.result; } // Prototype method to subtract numbers subtract(a, b) { this.result = a - b; return this.result; } // Prototype method to multiply numbers multiply(a, b) { this.result = a * b; return this.result; } // Prototype method to divide numbers divide(a, b) { if (b === 0) throw new Error("Division by zero is not allowed."); this.result = a / b; return this.result; } } // Step 2: Create a proxy handler to intercept operations const handler = { // Intercept 'get' operations to ensure access to prototype methods get(target, prop, receiver) { if (prop in target) { console.log(`Accessing property: ${prop}`); return Reflect.get(target, prop, receiver); // Access property safely } else { throw new Error(`Property "${prop}" does not exist.`); } }, // Intercept 'set' operations to prevent mutation set(target, prop, value) { throw new Error(`Cannot modify property "${prop}". The calculator is immutable.`); } }; // Step 3: Create a proxy instance that inherits the Calculator prototype const calculator = new Calculator(); // Original calculator object const proxiedCalculator = new Proxy(calculator, handler); // Proxy wrapping the calculator // Step 4: Use the proxy instance try { console.log(proxiedCalculator.add(5, 3)); // Output: 8 console.log(proxiedCalculator.multiply(4, 2)); // Output: 8 console.log(proxiedCalculator.divide(10, 2)); // Output: 5 // Attempt to access prototype directly through proxy console.log(proxiedCalculator.__proto__ === Calculator.prototype); // Output: true // Attempt to modify a property (should throw an error) proxiedCalculator.result = 100; // Error: Cannot modify property "result". } catch (error) { console.error(error.message); // Output: Cannot modify property "result". The calculator is immutable. }
この方法でプロキシを使用する最良の部分:
- プロキシ オブジェクトは、元の Calculator クラスのプロトタイプを継承します。
- 突然変異は、プロキシの設定されたトラップによって回避されます。
コードの説明
1)。 プロトタイプの継承:
2)。 getOperations の処理:
3)。 突然変異の防止:
ターゲット オブジェクトのプロパティを変更しようとするたびに、設定されたトラップはエラーをスローします。これにより不変性が保証されます。
4)。 プロキシを介したプロトタイプ メソッドの使用:
プロキシを使用すると、元のオブジェクトのプロトタイプで定義されている加算、減算、乗算、除算などのメソッドにアクセスできます。
ここで注意すべき重要なポイントは次のとおりです:
ここまで進んだ場合は、忘れずに「いいね!」を押して、質問や意見があれば下にコメントを残してください。あなたのフィードバックは私にとってとても大切なものです。ぜひご意見をお待ちしております!
免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。
Copyright© 2022 湘ICP备2022001581号-3