27代理模式(Proxy Pattern)
直接與間接:
?? 人們對復雜的軟件系統常有一種處理手法,即增加一層間接層,從而對系統獲得一種更為靈活、
滿足特定需求的解決方案。? ???
? ? ? ? ? ? ? ? ? ? ?? ????????????????????????????????????????????????????????????????????????????????? ????
?????
動機(Motivate):
??? 在面向對象系統中,有些對象由于某種原因(比如對象創建的開銷很大,或者某些操作需要安全控制,或者需要進程外的訪問等),直接訪問會給使用者、或者系統結構帶來很多麻煩。
??? 如何在不失去透明操作對象的同時來管理/控制這些對象特有的復雜性?增加一層間接層是軟件開發中常見的解決方式。
意圖(Intent):
??? ???為其他對象提供一種代理以控制對這個對象的訪問。? -------《設計模式》GOF
結構圖(Struct):
????????????????????
生活中的例子:
??? ???代理模式提供一個中介以控制對這個對象的訪問。一張支票或銀行存單是賬戶中資金的代理。支票在市場交易中用來代替現金,并提供對簽發人賬號上資金的控制。
????????????????????
代碼實例:
????在軟件系統 中,我們無時不在跨越障礙,當我們訪問網絡上一臺計算機的資源時,我們正在跨越網絡障礙,當我們去訪問服務器上數據庫時,我們又在跨越數據庫訪問障礙,同 時還有網絡障礙。跨越這些障礙有時候是非常復雜的,如果我們更多的去關注處理這些障礙問題,可能就會忽視了本來應該關注的業務邏輯問題,Proxy模式有助于我們去解決這些問題。我們以一個簡單的數學計算程序為例,這個程序只負責進行簡單的加減乘除運算:
?1?public?class?Math
?2?{
?3?????public?double?Add(double?x,double?y)
?4?????{
?5?????????return?x?+?y;
?6?????}
?7?
?8?????public?double?Sub(double?x,double?y)
?9?????{
10?????????return?x?-?y;
11?????}
12?
13?????public?double?Mul(double?x,double?y)
14?????{
15?????????return?x?*?y;
16?????}
17?
18?????public?double?Dev(double?x,double?y)
19?????{
20?????????return?x?/?y;
21?????}
22?}
如果說這個計算程序部署在我們本地計算機上,使用就非常之簡單了,我們也就不用去考慮Proxy模式了。但現在問題是這個Math類并沒有部署在我們本地,而是部署在一臺服務器上,也就是說Math類根本和我們的客戶程序不在同一個地址空間之內,我們現在要面對的是跨越Internet這樣一個網絡障礙:
???????????????????
這時候調用Math類的方法就沒有下面那么簡單了,因為我們更多的還要去考慮網絡的問題,對接收到的結果解包等一系列操作。
?1?public?class?App
?2?{
?3?????public?static?void?Main()
?4?????{
?5?????????Math?math?=?new?Math();
?6?
?7?????????//?對接收到的結果數據進行解包
?8?
?9?????????double?addresult?=?math.Add(2,3);
10?
11?????????double?subresult?=?math.Sub(6,4);
12?
13?????????double?mulresult?=?math.Mul(2,3);
14?
15?????????double?devresult?=?math.Dev(2,3);
16?????}
17?}
為了解決由于網絡等障礙引起復雜性,就引出了Proxy模式,我們使用一個本地的代理來替Math類打點一切,即為我們的系統引入了一層間接層,示意圖如下:
??? ?? ?? ???
我們在MathProxy中對實現Math數據類的訪問,讓MathProxy來代替網絡上的Math類,這樣我們看到MathProxy就好像是本地Math類,它與客戶程序處在了同一地址空間內:
??? ?? ?? ?? ???
?1?public?class?MathProxy
?2?{
?3?????private?Math?math?=?new?Math();
?4?
?5?????//?以下的方法中,可能不僅僅是簡單的調用Math類的方法
?6?
?7?????public?double?Add(double?x,double?y)
?8?????{
?9?????????return?math.Add(x,y);
10?????}
11?
12?????public?double?Sub(double?x,double?y)
13?????{
14?????????return?math.Sub(x,y);
15?????}
16?
17?????public?double?Mul(double?x,double?y)
18?????{
19?????????return?math.Mul(x,y);
20?????}
21?
22?????public?double?Dev(double?x,double?y)
23?????{
24?????????return?math.Dev(x,y);
25?????}
26?}
????現在可以說我們已經實現了對Math類的代理,存在的一個問題是我們在MathProxy類中調用了原實現類Math的方法,但是Math并不一定實現了所有的方法,為了強迫Math類實現所有的方法,另一方面,為了我們更加透明的去操作對象,我們在Math類和MathProxy類的基礎上加上一層抽象,即它們都實現與IMath接口,示意圖如下:
??? ?? ?
?1?public?interface?IMath
?2?{
?3?????double?Add(double?x,double?y);
?4?
?5?????double?Sub(double?x,double?y);
?6?
?7?????double?Mul(double?x,double?y);
?8?
?9?????double?Dev(double?x,double?y);
10?}
11?
12?Math類和MathProxy類分別實現IMath接口:
13?
14?public?class?MathProxy?:?IMath
15?{
16?????//
17?}
18?
19?public?class?Math?:?IMath
20?{
21?????//
22?}
?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??
??? 此時我們在客戶程序中就可以像使用Math類一樣來使用MathProxy類了:
?1?public?class?App
?2?{
?3?????public?static?void?Main()
?4?????{
?5?????????MathProxy?proxy?=?new?MathProxy();
?6?
?7?????????double?addresult?=?proxy.Add(2,3);
?8?
?9?????????double?subresult?=?proxy.Sub(6,4);
10?
11?????????double?mulresult?=?proxy.Mul(2,3);
12?
13?????????double?devresult?=?proxy.Dev(2,3);
14?????}
15?}
到這兒整個使用Proxy模式的過程就完成了,回顧前面我們的解決方案,無非是在客戶程序和Math類之間加了一個間接層,這也是我們比較常見的解決問題的手段之一。另外,對于程序中的接口Imath,并不是必須的,大多數情況下,我們為了保持對對象操作的透明性,并強制實現類實現代理類所要調用的所有的方法,我們會讓它們實現與同一個接口。但是我們說代理類它其實只是在一定程度上代表了原來的實現類,所以它們有時候也可以不實現于同一個接口。
代理模式實現要點:
1.遠程(Remote)代理:為一個位于不同的??? 地址空間的對象提供一個局域代表對象。這個不同的地址空間可以是在本機器中,也可是在另一臺機器中。遠程代理又叫做大使(Ambassador)。好處是系統可以將網絡的細節隱藏起來,使得客戶端不必考慮網絡的存在。客戶完全可以認為被代理的對象是局域的而不是遠程的,而代理對象承擔了大部份的網絡通訊工作。由于客戶可能沒有意識到會啟動一個耗費時間的遠程調用,因此客戶沒有必要的思想準備。
2.虛擬(Virtual)代理:根據需要創建一個資源消耗較大的對象,使得此對象只在需要時才會被真正創建。使用虛擬代理模式的好處就是代理對象可以在必要的時候才將被代理的對象加載;代理可以對加載的過程加以必要的優化。當一個模塊的加載十分耗費資源的情況下,虛擬代理的好處就非常明顯。
3.Copy-on-Write代理:虛擬代理的一種。把復制(克隆)拖延到只有在客戶端需要時,才真正采取行動。
4.保護(Protect or Access)代理:控制對一個對象的訪問,如果需要,可以給不同的用戶提供不同級別的使用權限。保護代理的好處是它可以在運行時間對用戶的有關權限進行檢查,然后在核實后決定將調用傳遞給被代理的對象。
5.Cache代理:為某一個目標操作的結果提供臨時的存儲空間,以便多個客戶端可以共享這些結果。
6.防火墻(Firewall)代理:保護目標,不讓惡意用戶接近。
7.同步化(Synchronization)代理:使幾個用戶能夠同時使用一個對象而沒有沖突。
8.智能引用(Smart Reference)代理:當一個對象被引用時,提供一些額外的操作,比如將對此對象調用的次數記錄下來等。
?
總結
以上是生活随笔為你收集整理的27代理模式(Proxy Pattern)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ASP.NET Core管道深度剖析(4
- 下一篇: iPhone 14 Pro/Max跑分曝