首頁  >  文章  >  web前端  >  代理設計模式

代理設計模式

DDD
DDD原創
2024-10-19 12:36:01316瀏覽

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 方法顯示)。
  • 載入後,將使用顯示方法來顯示圖片。

2)。代理圖像:

  • ProxyImage類別充當RealImage的替代品。它不會立即載入真實圖像。
  • 它包含對真實圖像的引用(但最初它是空的,因為真實圖像尚未加載)。
  • 當您在代理程式上呼叫顯示方法時,它會檢查真實圖像是否已載入。如果沒有,它會先加載,然後顯示。

3)。用法:

  • 當我們建立 ProxyImage 實例時,實際映像尚未載入(因為它是資源密集的)。
  • 第一次呼叫 display 時,代理程式會載入圖片(使用 RealImage 類別),然後顯示它。
  • 第二次呼叫display時,真實圖片已經載入完畢,所以只顯示圖片,不再載入。

內建Proxy對象

ES6 代理由一個代理建構函式組成,建構函式接受目標和處理程序作為參數

const proxy = new Proxy(target, handler)

這裡,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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn