設計模式-結構型-代理模式

来源:https://www.cnblogs.com/az4215/archive/2019/09/21/11562848.html
-Advertisement-
Play Games

代理模式(Proxy): 代理模式就是給某一個對象提供一個代理,並由代理對象控制對原有對象的引用。在一些情況下,一個客戶不想或者不能直接引用一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。例如windows桌面端的快捷方式就是一個代理。 代理模式按照使用目的可以分為: 1)遠程代理:為 ...


代理模式(Proxy):

  代理模式就是給某一個對象提供一個代理,並由代理對象控制對原有對象的引用。在一些情況下,一個客戶不想或者不能直接引用一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。例如windows桌面端的快捷方式就是一個代理。

代理模式按照使用目的可以分為:

  1)遠程代理:為一個位於不同的地址空間的對象提供一個局域代表對象。這個不同的地址空間可以是本電腦中,也可以在另一臺電腦中。如客戶端調用web服務或wcf服務。

  2)虛擬代理:根據需要創建一個資源消耗較大的對象,使得對象只在需要時才會被真正創建。

  3)Copy-on-Write代理:虛擬代理的一種,把複製(或克隆)拖延到只有在客戶端需要時,才真正採取行動。

  4)保護(Protected or Access)代理:控制一個對象的訪問,可以給不同的用戶提供不同級別的使用許可權。

  5)Cache代理:為某一個目標操作的結果提供臨時的存儲空間,以便多個客戶端可以操作這些結果。

  6)防火牆(FireWall)代理:保護目標不讓惡意用戶接近。

  7)同步化(Synchronization)代理

  8)智能引用(Smart Reference)代理:當一個對象被引用時,提供一些額外的操作,比如將對此對象調用的次數記錄下來。

接下來以一個需求案例來說明下代理模式:

  現有收費商務信息查詢系統的二次開發,增加需求:

    1)添加用戶身份驗證;2)添加日誌記錄;3)要求以松耦合的方式進行功能添加

     

  1 internal class Program
  2 {
  3     private static void Main(string[] args)
  4     {
  5         /*
  6          * <?xml version="1.0" encoding="utf-8" ?>
  7          * <configuration>
  8          *  <appSettings>
  9          *      <add key="proxy" value="Proxy,Proxy.ProxySearcher" />
 10          *  </appSettings>
 11          * </configuration>
 12          */
 13         var proxy = ConfigurationManager.AppSettings["proxy"].Split(",");
 14         var searcher = (Searcher)Assembly.Load(proxy[0]).CreateInstance(proxy[1]);
 15         var result = searcher.DoSearch("楊過", "玉女心經");
 16     }
 17 }
 18 
 19 /// <summary>
 20 /// (1) AccessValidator:身份驗證類,業務類,它提供方法Validate()來實現身份驗證。
 21 /// </summary>
 22 internal class AccessValidator
 23 {
 24     //模擬實現登錄驗證
 25     public bool Validate(string userId)
 26     {
 27         Console.WriteLine($"在資料庫中驗證用戶{userId}是否是合法用戶?");
 28         if (userId.Equals("楊過"))
 29         {
 30             Console.WriteLine("'{0}'登錄成功!", userId);
 31             return true;
 32         }
 33         else
 34         {
 35             Console.WriteLine("'{0}'登錄失敗!", userId);
 36             return false;
 37         }
 38     }
 39 }
 40 
 41 /// <summary>
 42 /// (2) Logger:日誌記錄類,業務類,它提供方法Log()來保存日誌。
 43 /// </summary>
 44 internal class Logger
 45 {
 46     //模擬實現日誌記錄
 47     public void Log(string userId)
 48     {
 49         Console.WriteLine($"更新資料庫,用戶{userId}查詢次數加1!");
 50     }
 51 }
 52 
 53 /// <summary>
 54 /// (3) Searcher:抽象查詢類,充當抽象主題角色,它聲明瞭DoSearch()方法。
 55 /// </summary>
 56 internal interface Searcher
 57 {
 58     string DoSearch(string userId, string keyWord);
 59 }
 60 
 61 /// <summary>
 62 /// (4) RealSearcher:具體查詢類,充當真實主題角色,它實現查詢功能,提供方法DoSearch()來查詢信息。
 63 /// </summary>
 64 internal class RealSearcher : Searcher
 65 {
 66     public string DoSearch(string userId, string keyWord)
 67     {
 68         Console.WriteLine($"用戶{userId}使用關鍵詞{keyWord}查詢商務信息!");
 69         return "返回具體內容";
 70     }
 71 }
 72 
 73 /// <summary>
 74 /// (5) ProxySearcher:代理查詢類,充當代理主題角色,它是查詢代理,維持了對RealSearcher對象、AccessValidator對象和Logger對象的引用。
 75 /// </summary>
 76 internal class ProxySearcher : Searcher
 77 {
 78     private Searcher searcher;
 79     private AccessValidator validator;
 80     private Logger logger;
 81 
 82     public ProxySearcher()
 83     {
 84         searcher = new RealSearcher();
 85     }
 86 
 87     public string DoSearch(string userId, string keyword)
 88     {
 89         //如果身份驗證成功,則執行查詢
 90         if (this.Validate(userId))
 91         {
 92             string result = searcher.DoSearch(userId, keyword); //調用真實主題對象的查詢方法
 93             this.Log(userId); //記錄查詢日誌
 94             return result; //返回查詢結果
 95         }
 96         else
 97         {
 98             return null;
 99         }
100     }
101 
102     //創建訪問驗證對象並調用其Validate()方法實現身份驗證
103     public bool Validate(string userId)
104     {
105         validator = new AccessValidator();
106         return validator.Validate(userId);
107     }
108 
109     //創建日誌記錄對象並調用其Log()方法實現日誌記錄
110     public void Log(string userId)
111     {
112         logger = new Logger();
113         logger.Log(userId);
114     }
115 }

  代理模式角色分四種:

    1)主題介面(Searcher):定義代理類和真實主題的公共對外方法,也是代理類代理真實主題的方法;

    2)真實主題(RealSeracher):真正實現業務邏輯的類;

    3)代理類(ProxySeracher):用來代理和封裝真實主題;

    4)客戶端:使用代理類和主題完成工作。

代理模式的優缺點:

  優點:

    1)代理模式能夠將調用用於真正被調用的對象隔離,在一定程度上降低了系統的耦合度;

    2)代理對象在客戶端和目標對象之間起到一個中介的作用,這樣可以起到對目標對象的保護。代理對象可以在對目標對象發出請求之前進行一個額外的操作,例如許可權檢查等。

  缺點:

    1)由於在客戶端和真實主題之間增加了一個代理對象,所以會造成請求的處理速度變慢;

    2)實現代理類也需要額外的工作,從而增加了系統的實現複雜度。

代理模式與適配器模式的區別?

  學習完適配器模式和代理模式之後,會產生這樣的疑問:貌似兩種模式差不多?兩者都是定義了一個目標對象(抽象對象),客戶端依賴該抽象對象完成相應功能,這麼一解釋好像是一樣的,那為什麼大牛們會分成兩種模式呢?適配器模式是因為新舊介面不一致導致出現了客戶端無法得到滿足的問題,但由於舊的介面是不能被完全重構掉的,因為我們還想使用實現了這個介面的一些服務。那麼為了使用以前實現舊介面的服務,我們就應該把新的介面轉換成舊介面;實現這個轉換的類就是抽象意義的轉換器。相比於適配器的應用場景,代理就不一樣了,雖然代理也同樣是增加了一層,但是,代理提供的介面和原本的介面是一樣的,代理模式的作用是不把實現直接暴露給客戶端,而是通過代理這個層,代理能夠做一些處理。

代理模式與委托的區別?

  1)代理是模式提供一種"一個類對另外一個類的控制權"是類與類之間關係;委托提供了"一種方法的執行會同時執行載入在上面的方法"是方法與方法之間的關係。

  2)委托可以代替代理,但是代理不能代替委托。

  3)委托可以動態載入方法,代理不能實現。

  4)委托對象所載入的方法不一定要屬於同一個類。但是代理的類必須屬於同一個類。   

參考:https://blog.csdn.net/lovelion/article/details/8228042 

  https://www.cnblogs.com/zhili/p/ProxyPattern.html 

  https://www.cnblogs.com/chenwolong/p/Proxy.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 0921自我總結 css3如何解決動畫的播放、暫停和重新開始 一.解決的本質思路 播放的解決思路 先定義好動畫效果通過類名的增加達到樣式的出現 暫停的解決思路 我們播放動畫時,如要暫停動畫,就要用到 這個屬性。 屬性有兩個值: 當然去掉 ,也可以繼續播放動畫。 重新開始解決思路 播放與重新開始的解決 ...
  • JavaScript 變數 概述 把一個具體的值存入到變數中。那麼此時這個變數就代表著我們這個具體的值。我們如果想要重新的使用這個值,不再需要重新的計算或者其他操作,直接使用變數就可以得到之前存儲的這個值。 簡單的說,變數就是一個保存數據的容器,調用變數就是調用保存在這個容器中的值。 變數之所以叫做 ...
  • <input type="file" id='file'> <div> <img src="" alt="" id='preview'> </div> <script> let file = document.querySelector('#file'); let preview = documen ...
  • 工作中遇到需要根據不同數據來處理模板word的情況,網上搜索了一番之後,找到了一個叫做docxtemplater的庫,使用起來非常便攜,也十分滿足此次的需求。 這次就來記錄一下docxtemplater的使用。 docxtemplater官網:https://docxtemplater.readth ...
  • 文章原創於公眾號:程式猿周先森。本平臺不定時更新,喜歡我的文章,歡迎關註我的微信公眾號。 其實在JavaScript的發展中,它主要是在瀏覽器前端中被應用廣泛。因為在實際應用中, JavaScript的表現能力主要取決於宿主環境的API支持程度, 在最早期,只有對BOM, DOM的支持,隨著HTML ...
  • 場景 Ubuntu Server 上使用Docker Compose 部署Nexus(圖文教程): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/101111611 在上面已經實現部署Nexus後,初次登錄的預設賬戶密碼: adm ...
  • 場景 Docker-Compose簡介與Ubuntu Server 上安裝Compose: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100902301 Docker Compose基本使用-使用Compose啟動Tomcat ...
  • 場景 Docker-Compose簡介與Ubuntu Server 上安裝Compose: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100902301 Docker Compose基本使用-使用Compose啟動Tomcat ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...