自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

掌握C# 中的代理設(shè)計(jì)模式(Proxy Design Pattern)

開發(fā) 前端
在本文中,我將通過示例討論 C# 中的代理設(shè)計(jì)模式(Proxy Design Pattern)。 代理設(shè)計(jì)模式屬于結(jié)構(gòu)設(shè)計(jì)模式的范疇。 作為本文的一部分,我們將討論以下幾點(diǎn)。

什么是代理設(shè)計(jì)模式?

根據(jù) Gang of four 的定義,代理設(shè)計(jì)模式為另一個(gè)對象提供了一個(gè)代理(代表其他行動(dòng)人)或占位符來控制對它的訪問。 代理是指“代替”或“代表”。

在最簡單的形式中,我們可以將代理定義為一個(gè)類,作為其他東西的接口。 代理可以連接到任何東西,例如網(wǎng)絡(luò)連接、內(nèi)存中的大型對象、文件或其他一些昂貴或無法復(fù)制的資源。

我們也可以說代理(Proxy)是客戶端(Client)調(diào)用的對象,用于訪問幕后的真實(shí)對象。 這意味著,在代理設(shè)計(jì)模式中,一個(gè)類代表另一個(gè)類的功能。

通過示例了解 C# 中的代理設(shè)計(jì)模式:

請查看下圖以更好地理解 C# 中的代理設(shè)計(jì)模式。 正如您在下圖中看到的,當(dāng)客戶端想要使用真實(shí)對象的某些方法時(shí),他/她需要通過代理對象。 這意味著客戶端將調(diào)用代理對象的方法,而代理將負(fù)責(zé)調(diào)用真實(shí)對象的方法。

代理的類型:

有三種類型的代理。 它們?nèi)缦隆?/span>

  1. 虛擬代理:虛擬代理是“昂貴創(chuàng)建”對象的占位符。 真正的對象僅在客戶端首次請求或訪問該對象時(shí)創(chuàng)建。
  2. 遠(yuǎn)程代理:遠(yuǎn)程代理為駐留在不同地址空間中的對象提供本地表示。
  3. 保護(hù)代理:保護(hù)代理控制對敏感對象的訪問。 代理對象在轉(zhuǎn)發(fā)請求之前檢查調(diào)用者是否具有所需的訪問權(quán)限。

代理設(shè)計(jì)模式真實(shí)示例:

請看下圖。 在右側(cè),您可以看到銀行,在左側(cè)可以看到一個(gè)叫 Anurag 的人。 Anurag 在銀行有一個(gè)賬戶。 在早些時(shí)候,比如說 1960 年,Anurag 想從他的賬戶中取款。 那么他要做的就是,他必須帶著他的存折去銀行。 然后他必須填寫表格并需要排隊(duì)。 輪到他時(shí),他必須將表格和銀行存折交給銀行員工,然后銀行員工驗(yàn)證表格和他的存折,如果一切正常,則銀行員工將所需的錢交給 Anurag。

假設(shè) Anurag 現(xiàn)在想取錢。 因此,他現(xiàn)在能做的不是去銀行,而是拿著銀行卡到最近的 ATM。 然后他插入他的銀行卡并輸入密碼和提款金額。 然后 ATM 將與銀行通信并驗(yàn)證密碼和金額,如果一切正常,ATM 將把錢交給 Anurag。 Anurag 無需去銀行,直接從 ATM 取款。 因此,這里的銀行是真實(shí)對象,ATM 是代理。 我認(rèn)為這是代理設(shè)計(jì)模式的最佳真實(shí)示例。

為什么我們需要 C# 中的代理設(shè)計(jì)模式?

讓我們以代理服務(wù)器為例來了解代理設(shè)計(jì)模式的必要性。

位于客戶端應(yīng)用程序(例如 Web 瀏覽器)和真實(shí)服務(wù)器之間的服務(wù)器稱為代理服務(wù)器。 該代理服務(wù)器攔截所有傳入的真實(shí)服務(wù)器請求,以查看它是否可以自行完成請求。 如果不是,那么它會(huì)將請求轉(zhuǎn)發(fā)到真實(shí)服務(wù)器。

代理服務(wù)器有兩個(gè)主要目標(biāo)。 它們?nèi)缦拢?/span>

提高性能:

代理服務(wù)器可以極大地提高應(yīng)用程序的性能。 這是因?yàn)樗鼘⒄埱蟮慕Y(jié)果保存了一段時(shí)間。 例如,假設(shè)我們有兩個(gè)用戶 X 和 Y,他們想通過代理服務(wù)器訪問特定資源。 首先,用戶 X 請求一個(gè)特定的資源(比方說一個(gè)員工列表)并將該資源緩存一段時(shí)間。 稍后,用戶 Y 也請求相同的資源,代理服務(wù)器不再將該請求轉(zhuǎn)發(fā)給實(shí)際服務(wù)器(這是一項(xiàng)耗時(shí)操作),只需從緩存中返回?cái)?shù)據(jù)即可。 由于客戶端和代理服務(wù)器在同一個(gè)網(wǎng)絡(luò)中,因此操作速度會(huì)快得多。

過濾請求:

代理服務(wù)器也可用于過濾傳入的請求。 例如,一家公司可能會(huì)使用代理服務(wù)器來阻止其員工訪問一組特定的網(wǎng)站,如某寶、拼某多等。

C#中代理設(shè)計(jì)模式的實(shí)現(xiàn)(保護(hù)代理):

業(yè)務(wù)要求:

請看下圖。 正如您在下圖中看到的,在右側(cè)我們有一臺(tái)共享文件夾的共享計(jì)算機(jī)。 在左側(cè),我們有在軟件農(nóng)場工作的員工。 共享計(jì)算機(jī)包含一個(gè)包含機(jī)密信息的共享文件夾,只有具有經(jīng)理和首席執(zhí)行官角色的員工才能訪問此共享文件夾并執(zhí)行讀寫操作。 另一方面,如果員工是開發(fā)人員,則不應(yīng)允許訪問共享文件夾。 那就是我們需要做某種保護(hù)。 在這種情況下,保護(hù)代理可以派上用場。

我們在這里可以做的是,在員工和共享計(jì)算機(jī)之間,我們需要引入文件夾代理。 這個(gè)文件夾代理可以做的是,它會(huì)檢查員工的角色是經(jīng)理還是首席執(zhí)行官,然后允許員工訪問共享文件夾并執(zhí)行讀寫操作。 另一方面,如果員工角色是 Developer 那么它會(huì)說你沒有權(quán)限訪問這個(gè)文件夾。 保護(hù)邏輯我們可以寫在文件夾代理中。

現(xiàn)在,我希望您了解代理設(shè)計(jì)模式。 那么,讓我們一步步在C#中實(shí)現(xiàn)代理設(shè)計(jì)模式吧。

第一步:創(chuàng)建員工類

創(chuàng)建一個(gè)名為 Employee.cs 的類文件,然后將以下代碼復(fù)制并粘貼到其中。

namespace ProxyDesignPattern
{
public class Employee
{
public string Username { get; set; }
public string Password { get; set; }
public string Role { get; set; }
public Employee(string username, string password, string role)
{
Username = username;
Password = password;
Role = role;
}
}
}

Step2:創(chuàng)建主體

創(chuàng)建一個(gè)名為 ISharedFolder 的接口,然后將以下代碼復(fù)制并粘貼到其中。 該接口定義了將由 RealSubject 和 Proxy 類實(shí)現(xiàn)的常用方法。

using System;
namespace ProxyDesignPattern
{
public interface ISharedFolder
{
void PerformRWOperations();
}
}

第三步:創(chuàng)建真實(shí)對象

創(chuàng)建一個(gè)名為 SharedFolder.cs 的類文件,然后將以下代碼復(fù)制并粘貼到其中。 此類實(shí)現(xiàn)主體 (ISharedFolder) 接口。

using System;
namespace ProxyDesignPattern
{
public class SharedFolder : ISharedFolder
{
public void PerformRWOperations()
{
Console.WriteLine("Performing Read Write operation on the Shared Folder");
}
}
}

第四步:創(chuàng)建代理對象

創(chuàng)建一個(gè)名為 SharedFolderProxy.cs 的類文件,然后將以下代碼復(fù)制并粘貼到其中。 此類還實(shí)現(xiàn)了 Subject (ISharedFolder) 接口,并且它還持有對真實(shí)對象的引用。

using System;
namespace ProxyDesignPattern
{
class SharedFolderProxy : ISharedFolder
{
private ISharedFolder folder;
private Employee employee;
public SharedFolderProxy(Employee emp)
{
employee = emp;
}
public void PerformRWOperations()
{
if (employee.Role.ToUpper() == "CEO" || employee.Role.ToUpper() =="MANAGER")
{
folder = new SharedFolder();
Console.WriteLine("Shared Folder Proxy makes call to the RealFolder 'PerformRWOperations method'");
folder.PerformRWOperations();
}
else
{
Console.WriteLine("Shared Folder proxy says 'You don't have permission to access this folder'");
}
}
}
}

Step5:客戶端代碼

請修改 Main 方法,如下所示。

using System;
namespace ProxyDesignPattern
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Client passing employee with Role Developer to folderproxy");
Employee emp1 = new Employee("Anurag", "Anurag123", "Developer");
SharedFolderProxy folderProxy1 = new SharedFolderProxy(emp1);
folderProxy1.PerformRWOperations();
Console.WriteLine();
Console.WriteLine("Client passing employee with Role Manager to folderproxy");
Employee emp2 = new Employee("Pranaya", "Pranaya123", "Manager");
SharedFolderProxy folderProxy2 = new SharedFolderProxy(emp2);
folderProxy2.PerformRWOperations();
Console.Read();
}
}
}

了解代理設(shè)計(jì)模式類圖:

為了理解 C# 中代理設(shè)計(jì)模式的類圖,請看下圖。

如上圖所示,代理設(shè)計(jì)模式涉及三個(gè)參與者。 它們?nèi)缦拢?/span>

  1. 主體(ISharedFolder): 這是一個(gè)定義將由 RealSubject 和 Proxy 類實(shí)現(xiàn)的成員的接口,以便可以在任何需要 RealSubject 的地方使用 Proxy。 在我們的示例中,它是 ISharedFolder 接口。
  2. 真實(shí)對象(SharedFolder): 這是一個(gè)我們希望通過使用代理類來更高效地使用的類。 在我們的示例中,它是 SharedFolder 類。
  3. 代理(SharedFolderProxy): 這是一個(gè)持有對 RealSubject 類的引用的類,可以根據(jù)需要訪問 RealSubjectr 類成員。 它必須實(shí)現(xiàn)與 RealSubject 相同的接口,以便兩者可以互換使用。 在我們的示例中,它是 SharedFolderProxy 類。

何時(shí)在 C# 實(shí)時(shí)應(yīng)用程序中使用代理設(shè)計(jì)模式?

以下是您可以在 C# 實(shí)時(shí)應(yīng)用程序中使用代理設(shè)計(jì)模式的一些實(shí)時(shí)場景。

  1. 添加對現(xiàn)有對象的安全訪問。 代理將確定客戶端是否可以訪問感興趣的對象。
  2. 簡化復(fù)雜對象的 API。 代理可以提供一個(gè)簡單的 API,這樣客戶端代碼就不必處理感興趣對象的復(fù)雜性。
  3. 為 Web 服務(wù)或 REST 資源等遠(yuǎn)程資源提供接口。
  4. 通過要求遠(yuǎn)程資源在訪問資源之前盡快開始操作來協(xié)調(diào)對遠(yuǎn)程資源的昂貴操作。
  5. 在不更改現(xiàn)有類代碼的情況下向現(xiàn)有類添加線程安全功能。


C# 中的代理設(shè)計(jì)模式實(shí)時(shí)示例 – 虛擬代理

虛擬代理是創(chuàng)建成本高昂的對象的占位符。 真正的對象只有在客戶第一次請求或訪問一個(gè)對象時(shí)才被創(chuàng)建。 讓我們通過一個(gè)實(shí)時(shí)示例來理解這一點(diǎn)。 請看下面的圖片。 在右側(cè),您可以看到系統(tǒng)A,它有一個(gè) 200 MB 的圖像(老虎圖像)。 在左側(cè),您可以看到客戶端。 在客戶端和系統(tǒng)A 之間,有充當(dāng)虛擬代理的系統(tǒng)B。

比方說,客戶端第一次向系統(tǒng) B(虛擬代理)發(fā)送請求以顯示老虎圖像。 虛擬代理(即系統(tǒng) B)要做的是,首先它會(huì)檢查虛擬代理中是否存在真實(shí)圖像對象。 如果真實(shí)圖像對象不存在,那么在第 1 步中它將創(chuàng)建真實(shí)圖像對象并從磁盤加載圖像,在第 2 步中它將調(diào)用真實(shí)圖像對象上的顯示圖像方法。 虛擬代理還保存在步驟 1 中創(chuàng)建的真實(shí)圖像對象。 第 1 步,即創(chuàng)建真實(shí)圖像對象并從磁盤加載圖像是一項(xiàng)昂貴的操作。

假設(shè)客戶端第二次向虛擬代理發(fā)出相同的請求以顯示老虎圖像。 現(xiàn)在,虛擬代理要做的是,檢查實(shí)像對象是否存在,它發(fā)現(xiàn)虛擬代理中存在實(shí)像對象(這是因?yàn)樵诘谝粋€(gè)請求中,虛擬代理持有真實(shí)- 圖像對象)。 所以,虛擬代理要做的是,它不會(huì)執(zhí)行第 1 步,即它不會(huì)創(chuàng)建真實(shí)圖像對象并從磁盤加載圖像。 相反,它將使用現(xiàn)有的真實(shí)圖像對象并調(diào)用 Display Image 方法,即 step2。 所以,通過這種方式,使用代理設(shè)計(jì)模式,我們可以避免一次又一次地創(chuàng)建一個(gè)昂貴的對象。

類圖:

請看下圖:

C#中代理設(shè)計(jì)模式實(shí)時(shí)實(shí)例的實(shí)現(xiàn):

讓我們使用代理設(shè)計(jì)模式逐步實(shí)現(xiàn)上述實(shí)時(shí)示例。 眾所周知,代理設(shè)計(jì)模式涉及三個(gè)組件,例如主題、真實(shí)對象和代理對象。 讓我們一一實(shí)現(xiàn)上面的組件。

第一步:創(chuàng)建主體

這將是一個(gè)接口。 因此,創(chuàng)建一個(gè)名為 IImage 的接口,然后將以下代碼復(fù)制并粘貼到其中。 該接口提供將由真實(shí)對象和代理對象具體類實(shí)現(xiàn)的功能。 在我們的示例中,接口定義了一種方法,即 DisplayImage

namespace ProxyDesignPattern
{
public interface IImage
{
void DisplayImage();
}
}

步驟2:創(chuàng)建真實(shí)對象

這將是一個(gè)具體類,此類實(shí)現(xiàn) IImage 接口并提供 DisplayImage 方法的實(shí)現(xiàn)。 因此,創(chuàng)建一個(gè)名為 RealImage.cs 的類文件,然后將以下代碼復(fù)制并粘貼到其中。 RealImage 類的這個(gè)構(gòu)造函數(shù)將文件名作為參數(shù),然后從磁盤加載文件。

using System;
namespace ProxyDesignPattern
{
public class RealImage : IImage
{
private string Filename { get; set; }
public RealImage(string filename)
{
Filename = filename;
LoadImageFromDisk();
}
public void LoadImageFromDisk()
{
Console.WriteLine("Loading Image : " + Filename);
}
public void DisplayImage()
{
Console.WriteLine("Displaying Image : " + Filename);
}
}
}

注意:這里的對象創(chuàng)建過程中有一個(gè)昂貴的操作。 這是因?yàn)樵趧?chuàng)建對象時(shí),它將從磁盤加載圖像。 LoadImageFromDisk 方法用于從磁盤加載圖像。 DisplayImage 方法只是用來顯示圖像。

第三步:創(chuàng)建代理

這將是一個(gè)具體類,它還實(shí)現(xiàn) IImage 接口并提供 DisplayImage 方法的實(shí)現(xiàn)。 因此,創(chuàng)建一個(gè)名為 ProxyObject.cs 的類文件,然后將以下代碼復(fù)制并粘貼到其中。 作為 DisplayImage 方法的一部分,首先,我們檢查 realImage 實(shí)例是否為 null。 如果為 null,則我們將創(chuàng)建實(shí)例,然后在 realImage 實(shí)例上調(diào)用 DisplayImage 方法。 另一方面,如果 realImage 實(shí)例不為 null,則它不會(huì)創(chuàng)建該實(shí)例,而是使用現(xiàn)有的 realImage 實(shí)例來調(diào)用 DisplayImage 方法。

namespace ProxyDesignPattern
{
public class ProxyImage : IImage
{
private RealImage realImage = null;
private string Filename { get; set; }
public ProxyImage(string filename)
{
Filename = filename;
}
public void DisplayImage()
{
if(realImage == null)
{
realImage = new RealImage(Filename);
}
realImage.DisplayImage();
}
}
}

第四步:客戶端

請修改 Main 方法,如下所示。 首先,我們創(chuàng)建ProxyImage對象來顯示老虎圖像,然后調(diào)用3次DisplayImage方法。 在這種情況下,第一次調(diào)用 DisplayImage 方法將創(chuàng)建 RealImage 實(shí)例,因此它將從磁盤加載圖像。 但是從第二次調(diào)用 DisplayImage 方法開始,它將使用現(xiàn)有的 RealImage 實(shí)例,因此不會(huì)從磁盤加載圖像。 這個(gè)過程對于第二次創(chuàng)建代理對象以顯示獅子圖像也是相同的。

using System;
namespace ProxyDesignPattern
{
class Program
{
static void Main(string[] args)
{
IImage Image1 = new ProxyImage("Tiger Image");

Console.WriteLine("Image1 calling DisplayImage first time :");
Image1.DisplayImage(); // loading necessary
Console.WriteLine("Image1 calling DisplayImage second time :");
Image1.DisplayImage(); // loading unnecessary
Console.WriteLine("Image1 calling DisplayImage third time :");
Image1.DisplayImage(); // loading unnecessary
Console.WriteLine();
IImage Image2 = new ProxyImage("Lion Image");
Console.WriteLine("Image2 calling DisplayImage first time :");
Image2.DisplayImage(); // loading necessary
Console.WriteLine("Image2 calling DisplayImage second time :");
Image2.DisplayImage(); // loading unnecessary
Console.ReadKey();
}
}
}


責(zé)任編輯:姜華 來源: 今日頭條
相關(guān)推薦

2012-08-22 10:10:25

單態(tài)單態(tài)設(shè)計(jì)設(shè)計(jì)模式

2024-07-31 10:41:16

C#設(shè)計(jì)模式

2009-04-29 09:06:18

C#設(shè)計(jì)模式Adapter

2024-07-22 08:09:28

C#模式架構(gòu)

2009-08-26 10:24:04

C# Observer

2009-09-02 16:23:27

C# Singleto

2021-12-01 07:38:27

設(shè)計(jì)模式規(guī)格模式Specificati

2009-08-31 16:01:31

C#和設(shè)計(jì)模式

2021-11-10 11:13:02

C#設(shè)計(jì)模式

2009-09-07 04:59:12

C#模式窗體

2009-08-24 16:11:35

C#項(xiàng)目開發(fā)

2012-02-29 09:41:14

JavaScript

2012-01-13 15:59:07

2021-06-29 08:54:23

設(shè)計(jì)模式代理模式遠(yuǎn)程代理

2024-02-19 08:38:34

建造者模式Android設(shè)計(jì)模式

2022-11-30 17:05:33

代碼程序場景

2019-08-16 10:46:46

JavaScript工廠模式抽象工廠模式

2021-11-29 09:38:12

設(shè)計(jì)模式對象池模式Object Pool

2021-12-01 09:23:13

C# 模式套路

2024-07-22 14:34:20

簡單工廠模式C#
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)