22.代理模式:思考與解讀

原文地址:代理模式:思考與解讀? 更多內容請關注:深入思考與解讀設計模式

引言

在軟件開發中,尤其是當對象的訪問需要控制時,你是否遇到過這樣的問題:某些操作或對象可能需要進行額外的檢查、優化或延遲加載,或者你希望控制客戶端如何訪問一個資源?如果我們有一種方式,可以讓客戶端通過另一個對象來間接訪問原始對象,從而控制這個訪問過程,這樣的設計是否能提高系統的靈活性和安全性?

代理模式正是為了解決這個問題而設計的。它通過創建一個代理對象,控制客戶端對目標對象的訪問。你是否理解,為什么通過代理對象可以將訪問控制和目標對象的具體實現分離,從而使得系統更具擴展性和可維護性?

在本文中,我們將通過一系列問題,逐步引導你理解代理模式的核心思想、應用場景以及如何實現它。

什么是代理模式?

問題1:你是否曾經需要控制客戶端對某個對象的訪問?例如,是否希望對某些方法進行權限檢查,或者在某些情況下延遲加載對象?

假設你有一個對象,它非常耗時或者非常重要,且你希望控制哪些客戶端可以訪問它,或者在某些時候才創建它。你通常如何實現這樣的控制?

問題2:如果可以通過一個代理對象來控制對目標對象的訪問,是否能夠在不修改目標對象的情況下,增加額外的行為或控制?

代理模式通過引入一個代理對象來控制對目標對象的訪問。你是否理解,為什么這種設計方式可以在不改變目標對象的情況下,靈活地為其增加控制行為?

代理模式的核心概念

問題3:代理模式通常包含哪些角色?每個角色的職責是什么?

代理模式通常包含以下幾個核心角色:

  1. 主題接口(Subject):定義了目標對象和代理對象共同遵循的接口,通常包含一個request()方法。

  2. 真實主題(RealSubject):實現了Subject接口,執行實際的操作。

  3. 代理(Proxy):也實現了Subject接口,控制對RealSubject的訪問,可能會增加額外的行為或控制請求。

  4. 客戶端(Client):通過代理對象訪問目標對象。

你能理解這些角色是如何協同工作,確保代理對象可以控制對真實對象的訪問,并在訪問過程中加入額外的功能嗎?

問題4:為什么要通過代理對象來控制對真實對象的訪問?這種設計如何將訪問控制與真實對象的實現解耦?

代理對象負責管理對真實對象的訪問,能夠在不修改真實對象的情況下,為其增加行為。你是否理解,這種解耦如何使得系統更加靈活,且易于擴展?

問題5:代理模式如何通過延遲加載、權限控制或其他方式增加額外的功能?代理對象是如何決定是否將請求轉發給真實對象的?

代理對象可以在轉發請求之前執行額外的操作(如權限檢查、延遲加載等)。你能理解,為什么這種方式能夠幫助我們靈活地控制對象的行為,而不需要改變目標對象本身?

代理模式的實現

假設你正在開發一個系統,其中有一個圖片加載模塊,這個模塊加載圖片非常耗時。你希望通過代理模式來延遲加載圖片,直到真正需要它的時候。

步驟1:定義主題接口

from abc import ABC, abstractmethodclass Image(ABC):@abstractmethoddef display(self):pass

問題6:為什么我們需要定義一個主題接口(Image)?它的作用是什么?

Image接口定義了目標對象和代理對象共同遵循的接口。通過接口,我們可以確保代理對象和真實對象都具備相同的方法,使得客戶端代碼能夠通過統一的接口來訪問目標對象。你能理解,為什么這種設計讓代理對象能夠透明地控制對目標對象的訪問?

步驟2:定義真實主題類(真實對象)
class RealImage(Image):def __init__(self, filename: str):self.filename = filenameself.load_image()def load_image(self):print(f"Loading image: {self.filename}")def display(self):print(f"Displaying image: {self.filename}")

問題7:RealImage類是如何實現Image接口的?它的display()方法和load_image()方法有什么作用?

RealImage類實現了Image接口,并在load_image()方法中加載圖片,display()方法中展示圖片。你是否理解,為什么RealImage負責實際的加載和展示操作,而代理對象則不直接參與這些操作?

步驟3:定義代理類(Proxy)
class ProxyImage(Image):def __init__(self, filename: str):self.filename = filenameself.real_image = Nonedef display(self):if not self.real_image:self.real_image = RealImage(self.filename)self.real_image.display()

問題8:ProxyImage類是如何控制對RealImage的訪問的?為什么它需要延遲加載RealImage對象?

ProxyImage類通過display()方法來延遲加載RealImage對象。只有在第一次請求顯示圖片時,代理對象才會創建RealImage對象并加載圖片。你是否理解,為什么這種延遲加載能夠節省資源,且提高系統性能?

步驟4:客戶端代碼
def main():image1 = ProxyImage("image1.jpg")image2 = ProxyImage("image2.jpg")# 第一次訪問時,代理對象會加載圖片image1.display()  # Loading image: image1.jpg# Displaying image: image1.jpg# 第二次訪問時,代理對象不會再次加載圖片image1.display()  # Displaying image: image1.jpg# 延遲加載另一個圖片image2.display()  # Loading image: image2.jpg# Displaying image: image2.jpgif __name__ == "__main__":main()

問題9:在客戶端代碼中,如何通過代理對象來訪問真實對象?代理對象如何管理真實對象的加載和顯示?

客戶端通過代理對象訪問圖片,而不直接操作RealImage對象。代理對象會在第一次訪問時加載圖片,并在后續訪問中直接展示圖片。你是否理解,為什么代理對象能夠有效控制圖片的加載過程,并在客戶端與真實對象之間起到中介作用?

代理模式的優缺點

問題10:代理模式的優點是什么?它如何幫助我們控制對真實對象的訪問,并增加額外的行為?

代理模式通過在客戶端和真實對象之間插入代理層,使得我們能夠靈活地控制對真實對象的訪問。你是否理解,為什么通過代理可以添加權限控制、延遲加載等行為,而不需要修改真實對象的實現?

問題11:代理模式的缺點是什么?它是否可能增加系統的復雜性,尤其是在代理層過多的情況下?

代理模式引入了額外的代理層,可能會導致系統的復雜性增加。你是否認為,當代理層過多時,可能會使系統變得更加難以理解和維護?如何避免過度使用代理模式?

適用場景

問題12:代理模式適用于哪些場景?

代理模式特別適用于以下場景:

  • 當需要控制對對象的訪問時,例如,延遲加載、緩存控制等。

  • 當需要在不修改目標對象的情況下,增加訪問控制邏輯時,例如,安全檢查、權限控制等。

  • 當對象的創建代價高昂,且我們希望延遲對象的創建時。

你能想到其他適用場景嗎?例如,數據庫連接池、網絡請求代理等,是否也可以使用代理模式?

問題13:代理模式是否適用于所有場景?在某些情況下,是否有更合適的設計模式來替代代理模式?

雖然代理模式能夠很好地控制訪問,但在某些場景中,是否可以通過其他簡單的設計模式(如裝飾者模式、策略模式)來達到類似的效果?你是否認為,代理模式的引入可能會使得系統過于復雜,尤其是代理對象過多時?

接下來,我們將通過具體的代碼示例來加深理解代理模式。

代理模式深入解讀

一、引言

代理模式(Proxy Pattern)是一種結構型設計模式,它通過為另一個對象提供一個代理對象來控制對該對象的訪問。代理模式的核心思想是通過代理對象來間接訪問目標對象,以便可以在訪問目標對象時進行一些額外的操作,比如延遲加載、權限檢查、日志記錄等。


二、簡單理解:什么是代理模式?

1. 什么是代理模式?

代理模式的核心思想是:為目標對象提供一個代理對象,客戶端通過代理對象訪問目標對象。代理對象可以在請求目標對象之前或之后執行一些額外的操作,比如權限檢查、日志記錄、延遲加載等。代理模式通常用于控制對目標對象的訪問。

通俗地講,代理模式就像是你通過助手來與一個專家進行溝通。你不直接聯系專家,而是通過助手。助手可以幫你安排與專家的會面、傳達信息,甚至在你不方便的時候代替你進行某些操作。

2. 代理模式的組成部分

代理模式通常包含以下幾個部分:

  • 主題接口(Subject):定義了目標對象和代理對象的共同接口,客戶端通過這個接口與目標對象或代理對象進行交互。

  • 真實主題(RealSubject):實現了主題接口,包含具體的業務邏輯,是目標對象。

  • 代理對象(Proxy):實現了主題接口,控制對真實主題的訪問,并在必要時對請求進行處理。

  • 客戶端(Client):通過代理對象與目標對象進行交互。


三、用自己的話解釋:如何理解代理模式?

1. 類比實際生活中的場景

假設你想咨詢一個專家,但專家非常忙,不能直接見每一個人。這時,你可以通過他的秘書(代理對象)來安排會面。秘書會幫你篩選有價值的咨詢請求,確保你不會浪費專家的時間。如果秘書認為某個請求不重要,可能會拒絕這個請求;如果請求有價值,秘書會將你引薦給專家(真實主題)。

在編程中,代理模式通過創建代理對象,控制對目標對象的訪問。代理對象可以執行額外的操作(如延遲加載、權限檢查等),讓客戶端和目標對象的交互變得更加靈活和高效。

2. 為什么要使用代理模式?

使用代理模式的好處是,它能讓我們控制對目標對象的訪問。通過代理對象,我們可以在請求前或請求后做一些處理,如權限控制、延遲加載、緩存管理等。代理模式不僅能簡化客戶端代碼,還能提高系統的性能和安全性。


四、深入理解:代理模式的實現

接下來,我們通過一個具體的代碼示例來實現代理模式,幫助你更好地理解如何在代碼中使用這個模式。

示例:圖片顯示系統

假設我們有一個圖片顯示系統,其中圖片對象加載需要時間。如果我們每次都直接加載圖片,會浪費很多時間和資源。為了提高效率,我們可以使用代理模式,讓代理對象在首次加載圖片時進行延遲加載(即只在需要時加載圖片),而之后就直接使用已經加載的圖片。

1. 定義主題接口
# 主題接口:定義目標對象和代理對象的公共接口
class Image:def display(self):pass
2. 定義真實主題類:圖片
# 真實主題類:圖片
class RealImage(Image):def __init__(self, filename: str):self.filename = filenameself.load_image()def load_image(self):print(f"Loading image from {self.filename}...")def display(self):print(f"Displaying image: {self.filename}")
3. 定義代理類:圖片代理
# 代理類:圖片代理
class ProxyImage(Image):def __init__(self, filename: str):self.filename = filenameself.real_image = Nonedef display(self):if self.real_image is None:self.real_image = RealImage(self.filename)  # 延遲加載圖片self.real_image.display()  # 使用真實主題類的方法來顯示圖片
4. 客戶端代碼:使用代理加載和顯示圖片
# 客戶端代碼:通過代理對象加載和顯示圖片
proxy_image1 = ProxyImage("image1.jpg")
proxy_image2 = ProxyImage("image2.jpg")# 第一次顯示時,代理會加載圖片
proxy_image1.display()  # 輸出:Loading image from image1.jpg... Displaying image: image1.jpg
proxy_image2.display()  # 輸出:Loading image from image2.jpg... Displaying image: image2.jpg# 第二次顯示時,代理直接顯示已加載的圖片
proxy_image1.display()  # 輸出:Displaying image: image1.jpg
proxy_image2.display()  # 輸出:Displaying image: image2.jpg
代碼解析:
  1. Image?類:這是主題接口,定義了目標對象和代理對象的公共方法。display()?方法用于顯示圖片。

  2. RealImage?類:這是真實主題類,表示圖片對象。它實現了?Image?接口,并提供了加載和顯示圖片的方法。加載圖片的操作是比較耗時的,通常在首次請求時執行。

  3. ProxyImage?類:這是代理類,延遲加載圖片。它也實現了?Image?接口,但在首次調用?display()?方法時,代理會先創建?RealImage?對象并加載圖片。之后,它會直接調用?RealImage?的?display()?方法來顯示圖片。

  4. 客戶端代碼:客戶端通過代理對象來加載和顯示圖片,代理對象確保只有在需要時才會加載真實圖片,而后續的顯示操作直接通過代理對象完成。


五、解釋給別人:如何講解代理模式?

1. 用簡單的語言解釋

代理模式就像是你通過助手來處理一些復雜的事情。你不直接接觸專家,而是通過助手來安排和協調工作。代理對象可以做一些額外的事情,比如延遲加載、權限控制等,從而提高系統的效率和安全性。在編程中,代理模式通過代理對象來控制對目標對象的訪問,讓客戶端與目標對象之間的交互更加靈活。

2. 為什么要使用代理模式?

使用代理模式的好處是,它能夠控制對目標對象的訪問,避免客戶端直接與目標對象交互,從而能在目標對象訪問之前或之后執行一些附加操作。例如,可以使用代理來實現延遲加載(只有在需要時才加載資源)、權限驗證(在訪問目標對象之前進行身份驗證)等功能。


六、總結

代理模式通過引入代理對象控制對真實對象的訪問,并可以為其添加額外的行為或控制,如延遲加載、權限檢查等。這種設計能夠在不修改真實對象的情況下,為其增加靈活的控制邏輯。

然而,代理模式也可能導致系統復雜性增加,尤其是代理層過多時。因此,在使用代理模式時,需要根據具體的需求權衡其優勢和成本。

通過以上學習過程,我們可以得出以下結論:

  • 代理模式?通過引入代理對象來控制對目標對象的訪問,代理對象可以在請求前后執行一些附加操作,如延遲加載、權限檢查等。

  • 代理模式適用于那些需要控制訪問、增加額外功能或延遲處理的場景,例如延遲加載、緩存管理、權限控制等。

代理模式的優點:

  • 解耦:通過代理對象,客戶端與目標對象之間的直接依賴關系被解耦,使得系統更加靈活。

  • 附加功能:代理可以在訪問目標對象之前或之后增加額外的功能,如延遲加載、緩存、權限檢查等。

  • 提高性能:通過延遲加載和緩存機制,代理模式可以有效提高系統的性能。

代理模式的缺點:

  • 增加復雜性:引入代理對象可能會導致系統復雜度增加,尤其在代理對象的功能較多時。

  • 性能開銷:代理對象本身會引入一定的性能開銷,尤其在處理大量請求時,可能會影響系統性能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處:https://dhexx.cn/hk/5528881.html

如若內容造成侵權/違法違規/事實不符,請聯系我的編程經驗分享網進行投訴反饋,一經查實,立即刪除!


相關文章:

  • 互聯網大廠Java求職面試:AI與云原生架構實戰解析
  • BEVDepth- Acquisition of Reliable Depth for Multi-view 3D Object Detection
  • 深度學習-梯度消失和梯度爆炸
  • LiveWallpaperMacOS:讓你的 Mac 桌面動起來
  • CMake指令:source_group()
  • style scoped作用域
  • ??知識圖譜:重構認知的智能革命?
  • RISC-V特權模式及切換
  • github actions入門指南
  • promise詳細總結
  • ASP.NET Core OData 實踐——Lesson6使用Action(C#)
  • c++第三天(對象與構造函數)
  • mac10.15.7 安裝erlang23.3 源碼安裝(未完待續)
  • 【容器】docker使用問題處理
  • Flutter 與 Android 原生布局組件對照表(完整版)
  • Houdini-為人工智能訓練生成合成數據
  • 面試題——計算機網絡:HTTP和HTTPS的區別?
  • 深度學習論文: FastVLM: Efficient Vision Encoding for Vision Language Models
  • Docker Desktop無法在windows低版本進行安裝
  • [網頁五子棋][匹配模塊]服務器開發、用戶管理器(創建匹配請求/響應對象、處理連接成功、處理下線)
  • 力扣100題---字母異位詞分組
  • pycharm找不到高版本conda問題
  • craw4ai 抓取實時信息,與 mt4外行行情結合實時交易,基本面來覺得趨勢方向,搞一個外匯交易策略
  • 依賴nacos實例動態創建線程池并監聽服務上下線
  • 通義實驗室開源針對RAG的預訓練框架
  • 并發編程基礎:內存屏障(Memory Barriers)
  • OpenLayers 加載網格信息
  • 深入詳解(0020,0052) Frame of Reference UID在序列空間定位中的定義與作用
  • 如何設計高效的數據湖架構:存儲策略、Schema 演進與數據生命周期管理
  • 設計模式-依賴倒轉原則
  • JWT安全:接收無簽名令牌.【簽名算法設置為none繞過驗證】
  • webpack的安裝及其后序部分
  • 內聯盒模型基本概念?——前端面試中的隱形考點剖析
  • 【大模型原理與技術-毛玉仁】第一章 語言模型基礎
  • VR 汽車:引領生產與設計的革命性飛躍?
  • Windwos上執行javadoc命令報錯java.lang.IllegalArgumentException
  • C 語言學習筆記(結構體2)
  • BugKu Web滲透之矛盾
  • day023-網絡基礎與OSI七層模型
  • JVM與JMM深度解析:從Java 8到Java 21的演進
  • linux安裝ffmpeg7.0.2全過程
  • ArcGIS Pro裁剪影像
  • GPIO驅動實例代碼
  • 三十一、面向對象底層邏輯-SpringMVC九大組件之RequestToViewNameTranslator接口設計哲學
  • ubuntu國內鏡像源手動配置
  • Kubernetes ConfigMap (明文)使用詳解
  • 使用Nginx + Keepalived配置實現Web站點高可用方案
  • 深蘭科技董事長陳海波率隊考察南京,加速AI大模型區域落地應用
  • MCP Server的五種主流架構:從原理到實踐的深度解析
  • 54、C# 委托 (Delegate)