首頁 > 軟體

.Net結構型設計模式之代理模式(Proxy)

2022-05-25 22:01:12

一、動機(Motivate)

在物件導向系統中,有些物件由於某種原因(比如物件建立的開銷很大,或者某些操作需要安全控制,或者需要程序外的存取等),直接存取會給使用者、或者系統結構帶來很多麻煩。如何在不失去透明操作物件的同時來管理/控制這些物件特有的複雜性?增加一層間接層是軟體開發中常見的解決方式。

二、意圖(Intent)

為其他物件提供一種代理以控制對這個物件的存取。                                 ——《設計模式》GoF

三、結構圖(Structure)

四、模式的組成

代理模式所涉及的角色有三個:
(1)、抽象主題角色(Subject):宣告了真實主題和代理主題的公共介面,這樣一來在使用真實主題的任何地方都可以使用代理主題。
(2)、代理主題角色(Proxy):代理主題角色內部含有對真實主題的參照,從而可以操作真實主題物件;代理主題角色負責在需要的時候建立真實主題物件;代理角色通常在將使用者端呼叫傳遞到真實主題之前或之後,都要執行一些其他的操作,而不是單純地將呼叫傳遞給真實主題物件。
(3)、真實主題角色(RealSubject):定義了代理角色所代表的真實物件。
附:在WCF或者WebService的開發過程中,我們在使用者端新增服務參照的時候,在客戶程式中會新增一些額外的類,在使用者端生成的類扮演著代理主題角色,我們使用者端也是直接呼叫這些代理角色來存取遠端服務提供的操作。這個是遠端代理的一個典型例子。

五、代理模式的分類:

代理模式按照使用目的可以分為以下幾種:
(1)、遠端(Remote)代理:為一個位於不同的地址空間的物件提供一個局域代表物件。這個不同的地址空間可以是本電腦中,也可以在另一臺電腦中。最典型的例子就是——使用者端呼叫Web服務或WCF服務。
(2)、虛擬(Virtual)代理:根據需要建立一個資源消耗較大的物件,使得物件只在需要時才會被真正建立。
(3)、Copy-on-Write代理:虛擬代理的一種,把複製(或者叫克隆)拖延到只有在使用者端需要時,才真正採取行動。
(4)、保護(Protect or Access)代理:控制一個物件的存取,可以給不同的使用者提供不同級別的使用許可權。
(5)、防火牆(Firewall)代理:保護目標不讓惡意使用者接近。
(6)、智慧參照(Smart Reference)代理:當一個物件被參照時,提供一些額外的操作,比如將對此物件呼叫的次數記錄下來等。
(7)、Cache代理:為某一個目標操作的結果提供臨時的儲存空間,以便多個使用者端可以這些結果。
在上面所有種類的代理模式中,虛擬代理、遠端代理、智慧參照代理和保護代理較為常見的代理模式。

六、代理模式的具體實現

說起“代理模式”,其實很容易,現實生活中的例子也很多。明星的經紀人,國家的發言人都是代理的好例子。我們就用明星經紀人這個事情來介紹“代理模式”的實現吧。

/// <summary>
/// 大明星都有錢,有錢了,就可以請自己的經紀人了,有了經紀人,很多事情就不用自己親力親為。弄點緋聞,炒作一下子通過經紀人就可以名正言順的的操作了,萬一搞不好,自己也可以否認。
/// </summary>
static void Main(string[] args)
{
    //近期,Fan姓明星關注度有點下降,來點炒作
    AgentAbstract fan = new AgentPerson();
    fan.Speculation("偶爾出來現現身,為炒作造勢");

}


//該型別就是抽象Subject角色,定義代理角色和真實主體角色共有的介面方法
public abstract class AgentAbstract
{
    //該方法執行具體的炒作---該方法相當於抽象Subject的Request方法
    public virtual void Speculation(string thing)
    {
        Console.WriteLine(thing);
    }
}

//該型別是Fan姓明星,有錢有勢,想炒什麼炒什麼---相當於具體的RealSubject角色
public sealed class FanStar : AgentAbstract
{
    //有錢有勢,有背景啊
    public FanStar() { }

    //要有名氣,定期要炒作---就是RealSubject型別的Request方法
    public override void Speculation(string thing)
    {
        Console.WriteLine(thing);
    }
}

//該型別是代理型別----相當於具體的Proxy角色
public sealed class AgentPerson : AgentAbstract
{
    //這是背後的老闆,
    private FanStar boss;

    //老闆在後面發號施令
    public AgentPerson()
    {
        boss = new FanStar();
    }

    //炒作的方法,執行具體的炒作---就是Proxy型別的Request方法
    public override void Speculation(string thing)
    {
        Console.WriteLine("前期弄點緋聞,拍點野照");
        boss.Speculation(thing);
        Console.WriteLine("然後開發佈會,傷心哭泣,繼續撈錢");
    }
}

七、代理模式的實現要點:

“增加一層間接層”是軟體系統中對許多複雜問題的一種常見解決方法。在物件導向系統中,直接使用某些物件會來帶很多問題,作為間接層的Proxy物件便是解決這一問題的常用手段。具體Proxy設計模式的實現方法、實現粒度都相差很大,有些可能對單個物件做細粒度的控制,如copy-on-write技術,有些可能對元件模組提供抽象代理層,在架構層次對物件做Proxy。
Proxy並不一定要求保持介面的一致性,只要能夠實現間接控制,有時候損及一些透明性是可以接受的。

1、代理模式的優點:

(1)、代理模式能夠將呼叫用於真正被呼叫的物件隔離,在一定程度上降低了系統的耦合度;
(2)、代理物件在使用者端和目標物件之間起到一箇中介的作用,這樣可以起到對目標物件的保護。代理物件可以在對目標物件發出請求之前進行一個額外的操作,例如許可權檢查等。
不同型別的代理模式也具有獨特的優點,例如:

(1)、遠端代理為位於兩個不同地址空間物件的存取提供了一種實現機制,可以將一些消耗資源較多的物件和操作移至效能更好的計算機上,提高系統的整體執行效率。
(2)、虛擬代理通過一個消耗資源較少的物件來代表一個消耗資源較多的物件,可以在一定程度上節省系統的執行開銷。
(3)、緩衝代理為某一個操作的結果提供臨時的快取儲存空間,以便在後續使用中能夠共用這些結果,優化系統效能,縮短執行時間。
(4)、保護代理可以控制對一個物件的存取許可權,為不同使用者提供不同級別的使用許可權。

2、代理模式的缺點:

(1)、由於在使用者端和真實主題之間增加了一個代理物件,所以會造成請求的處理速度變慢
(2)、實現代理類也需要額外的工作,從而增加了系統的實現複雜度。

3、代理模式的使用場景:

代理模式的型別較多,不同型別的代理模式有不同的優缺點,它們應用於不同的場合:
(1)、 當用戶端物件需要存取遠端主機中的物件時可以使用遠端代理
(2)、當需要用一個消耗資源較少的物件來代表一個消耗資源較多的物件,從而降低系統開銷、縮短執行時間時可以使用虛擬代理,例如一個物件需要很長時間才能完成載入時。
(3)、當需要為某一個被頻繁存取的操作結果提供一個臨時儲存空間,以供多個使用者端共用存取這些結果時可以使用緩衝代理。通過使用緩衝代理,系統無須在使用者端每一次存取時都重新執行操作,只需直接從臨時緩衝區獲取操作結果即可。
(4)、 當需要控制對一個物件的存取,為不同使用者提供不同級別的存取許可權時可以使用保護代理
(5)、當需要為一個物件的存取(參照)提供一些額外的操作時可以使用智慧參照代理

八、.NET 中代理模式的實現

代理模式在Net的FCL中的實現也不少,框架級別的有,類級別的也有。框架級別的有WCF,Remoting,他們都需要生成原生的代理,然後通過代理存取程序外或者機器外的物件。類級別的有StringBuilder型別,StringBuilder其實就是一種代理,我們本意是想存取字串的,StringBuilder就是一種可變字串的代理,而且StringBuilder也沒有和String保持介面的一致性。

九、總結

到今天為止,我們設計模式的三個部分講完兩個部分了,第一個部分是“建立型”的設計模式,解決物件建立的問題,對物件建立的解耦。第二部分就是“結構型”的設計模式,所謂結構型設計模式模式,顧名思義討論的是類和物件的結構 ,主要用來處理類或物件的組合。它包括兩種型別,一是類結構型模式,指的是採用繼承機制來組合介面或實現;二是物件結構型模式,指的是通過組合物件的方式來實現新的功能。它包括介面卡模式、橋接模式、裝飾者模式、組合模式、外觀模式、享元模式和代理模式。設計模式到現在也說了不少了,但是看起來很多模式都很類似,之間好像很容轉換,有時候條件不同了,的確模式也可以轉換,但是不能肆意的轉換。為了避免思想的混亂,我們把“結構型”這個幾個設計模式,再總結一次,把握核心,理解使用場景。

  • 介面卡模式注重轉換介面,將不吻合的介面適配對接
  • 橋接模式注重分離介面與其實現,支援多維度變化
  • 組合模式注重統一介面,將“一對多”的關係轉化為“一對一”的關係
  • 裝飾者模式注重穩定介面,在此前提下為物件擴充套件功能
  • 外觀模式注重簡化介面,簡化元件系統與外部客戶程式的依賴關係
  • 享元模式注重保留介面,在內部使用共用技術對物件儲存進行優化
  • 代理模式注重假借介面,增加間接層來實現靈活控制

到此這篇關於.Net結構型設計模式之代理模式(Proxy)的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com