本筆記摘抄自:https://www.cnblogs.com/PatrickLiu/p/7814004.html,記錄一下學習程序以備后續查用,
一、引言
今天我們要講結構型設計模式的第七個模式,也是結構型設計模式中的最后一個模式--代理模式,先從名字上來看,“代理”可以理解為“代替”,代替“主人”
做一些事情,為什么需要“代理”?是因為某些原因(比如:安全方面的原因),不想讓“主人”直接面對這些繁瑣、復雜的問題,但是這些事情是經“主人”同意
或者授意的,如同“主人”親自完成的一樣,這個模式很簡單,生活中的例子也很多,舉例說明:歌星、影星的經紀人就是現實生活中一個代理模式的很好例
子,還有作業系統中的防火墻,也是代理的例子,要訪問系統,先過防火墻這關,否則免談,還有很多了,就不一一列舉了,大家在生活中慢慢地體會吧,
二、代理模式介紹
代理模式:英文名稱--Proxy Pattern;分類--結構型,
2.1、動機(Motivate)
在面向物件系統中,有些物件由于某種原因(比如物件創建的開銷很大,或者某些操作需要安全控制,或者需要行程外的訪問等),直接訪問會給使用者
或者系統結構帶來很多麻煩,如何在不失去透明操作物件的同時來管理/控制這些物件特有的復雜性?增加一層間接層是軟體開發中常見的解決方式,
2.2、意圖(Intent)
為其他物件提供一種代理以控制對這個物件的訪問,——《設計模式》GoF
2.3、結構圖(Structure)

2.4、模式的組成
代理模式所涉及的角色有三個:
1)抽象主題角色(Subject):宣告了真實主題和代理主題的公共介面,這樣一來在使用真實主題的任何地方都可以使用代理主題,
2)代理主題角色(Proxy):代理主題角色內部含有對真實主題的參考,從而可以操作真實主題物件;代理主題角色負責在需要的時候創建真實主題物件;
代理角色通常在將客戶端呼叫傳遞到真實主題之前或之后,都要執行一些其他的操作,而不是單純地將呼叫傳遞給真實主題物件,
3)真實主題角色(RealSubject):定義了代理角色所代表的真實物件,
附:在WCF或者WebService的開發程序中,我們在客戶端添加服務參考的時候,在客戶程式中會添加一些額外的類,在客戶端生成的類扮演著代理主題
角色,我們客戶端也是直接呼叫這些代理角色來訪問遠程服務提供的操作,這個是遠程代理的一個典型例子,
2.5、代理模式的分類
代理模式按照使用目的可以分為以下幾種:
1)遠程(Remote)代理:為一個位于不同的地址空間的物件提供一個局域代表物件,這個不同的地址空間可以是本電腦中,也可以在另一臺電腦中,最
典型的例子就是--客戶端呼叫Web服務或WCF服務,
2)虛擬(Virtual)代理:根據需要創建一個資源消耗較大的物件,使得物件只在需要時才會被真正創建,
3)Copy-on-Write代理:虛擬代理的一種,把復制(或者叫克隆)拖延到只有在客戶端需要時,才真正采取行動,
4)保護(Protect or Access)代理:控制一個物件的訪問,可以給不同的用戶提供不同級別的使用權限,
5)防火墻(Firewall)代理:保護目標不讓惡意用戶接近,
6)智能參考(Smart Reference)代理:當一個物件被參考時,提供一些額外的操作,比如將對此物件呼叫的次數記錄下來等,
7)Cache代理:為某一個目標操作的結果提供臨時的存盤空間,以便多個客戶端可以這些結果,
在上面所有種類的代理模式中,虛擬代理、遠程代理、智能參考代理和保護代理較為常見的代理模式,
2.6、代理模式的具體實作
說起代理模式,其實很容易,現實生活中的例子也很多,明星的經紀人,國家的發言人都是代理的好例子,
下面我們就用明星經紀人這個例子來介紹“代理模式”的實作吧,
class Program { /// <summary> /// 該型別就是抽象Subject角色,定義代理角色和真實主體角色共有的介面方法, /// </summary> public abstract class AgentAbstract { //該方法執行具體的炒作--該方法相當于抽象Subject的Request方法 public virtual void Speculation(string thing) { Console.WriteLine(thing); } } /// <summary> /// 該型別是Fan姓明星,有錢有勢,想炒什么就炒什么---相當于具體的RealSubject角色 /// </summary> public sealed class FanStar : AgentAbstract { //有錢有勢有背景啊 public FanStar() { } //要有名氣,定期要炒作---就是RealSubject型別的Request方法 public override void Speculation(string thing) { Console.WriteLine(thing); } } /// <summary> /// 該型別是代理型別--相當于具體的Proxy角色 /// </summary> public sealed class AgentPerson : AgentAbstract { //這是背后的老板 private readonly FanStar boss; //老板在后面發號施令 public AgentPerson() { boss = new FanStar(); } //炒作的方法,執行具體的炒作--就是Proxy型別的Request方法 public override void Speculation(string thing) { Console.WriteLine("前期弄點緋聞,拍點野照,"); boss.Speculation(thing); Console.WriteLine("然后開發布會,傷心哭泣,繼續撈錢,"); } } static void Main(string[] args) { #region 代理模式 //大明星都有錢,有錢就可以請自己的經紀人,有了經紀人,很多事情就不用自己親力親為, //弄點緋聞,炒作一下子通過經紀人就可以名正言順的地操作了,萬一搞不好,自己也可以否認, //近期,Fan姓明星關注度有點下降,來點炒作, AgentAbstract fan = new AgentPerson(); fan.Speculation("偶爾出來現現身,為炒作造勢,"); Console.WriteLine(); //過了段時間,又不行了,再炒作一次, fan.Speculation("這段時間不火了,開始離婚炒作,"); Console.Read(); #endregion } }View Code
運行結果如下:

這個模式很簡單,就話不多說了,
三、代理模式的實作要點
“增加一層間接層”是軟體系統中對許多復雜問題的一種常見解決方法,在面向物件系統中,直接使用某些物件會來帶很多問題,作為間接層的Proxy物件便
是解決這一問題的常用手段,具體Proxy設計模式的實作方法、實作粒度都相差很大,有些可能對單個物件做細粒度的控制,如copy-on-write技術,有些可能
對組件模塊提供抽象代理層,在架構層次對物件做Proxy,
Proxy并不一定要求保持介面的一致性,只要能夠實作間接控制,有時候損及一些透明性是可以接受的,
3.1、代理模式的優點
1)代理模式能夠將真正被呼叫的物件隔離,在一定程度上降低了系統的耦合度,
2)代理物件在客戶端和目標物件之間起到一個中介的作用,這樣可以起到對目標物件的保護,代理物件可以在對目標物件發出請求之前進行一個額外的操
作,例如權限檢查等,不同型別的代理模式也具有獨特的優點,例如:
(1)遠程代理為位于兩個不同地址空間物件的訪問提供了一種實作機制,可以將一些消耗資源較多的物件和操作移至性能更好的計算機上,提高系統的整
體運行效率,
(2)虛擬代理通過一個消耗資源較少的物件來代表一個消耗資源較多的物件,可以在一定程度上節省系統的運行開銷,
(3)緩沖代理為某一個操作的結果提供臨時的快取存盤空間,以便在后續使用中能夠共享這些結果,優化系統性能,縮短執行時間,
(4)保護代理可以控制對一個物件的訪問權限,為不同用戶提供不同級別的使用權限,
3.2、代理模式的缺點
1)由于在客戶端和真實主題之間增加了一個代理物件,所以會造成請求的處理速度變慢,
2)實作代理類也需要額外的作業,從而增加了系統的實作復雜度,
3.3、代理模式的使用場景
代理模式的型別較多,不同型別的代理模式有不同的優缺點,它們應用于不同的場合:
1) 當客戶端物件需要訪問遠程主機中的物件時可以使用遠程代理,
2)當需要用一個消耗資源較少的物件來代表一個消耗資源較多的物件,從而降低系統開銷、縮短運行時間時可以使用虛擬代理,例如一個物件需要很長時
間才能完成加載時,
3)當需要為某一個被頻繁訪問的操作結果提供一個臨時存盤空間,以供多個客戶端共享訪問這些結果時可以使用緩沖代理,通過使用緩沖代理,系統無須
在客戶端每一次訪問時都重新執行操作,只需直接從臨時緩沖區獲取操作結果即可,
4)當需要控制對一個物件的訪問,為不同用戶提供不同級別的訪問權限時可以使用保護代理,
5)當需要為一個物件的訪問(參考)提供一些額外的操作時可以使用智能參考代理,
四、.NET 中代理模式的實作
代理模式在Net的FCL中的實作也不少,框架級別的有,類級別的也有,框架級別的有WCF、Remoting,他們都需要生成本地的代理,然后通過代理訪問進
程外或者機器外的物件,類級別的有StringBuilder型別,StringBuilder其實就是一種代理,我們本意是想訪問字串的,StringBuilder就是一種可變字串的代
理,而且StringBuilder也沒有和String保持介面的一致性,
五、總結
到今天為止,我們設計模式的三個部分講完兩個部分了,第一個部分是“創建型”的設計模式,解決物件創建的問題,對物件創建的解耦,第二部分就是“結構型”
的設計模式,所謂結構型設計模式模式,顧名思義討論的是類和物件的結構,主要用來處理類或物件的組合,它包括兩種型別:一是類結構型模式,指的是采用
繼承機制來組合介面或實作;二是物件結構型模式,指的是通過組合物件的方式來實作新的功能,它包括配接器模式、橋接模式、裝飾者模式、組合模式、外觀
模式、享元模式和代理模式,設計模式到現在也說了不少了,但是看起來很多模式都很類似,之間好像很容轉換,有時候條件不同了,的確模式也可以轉換,但
是不能肆意的轉換,為了避免思想的混亂,我們把“結構型”這個幾個設計模式,再總結一次,把握核心,理解使用場景,
配接器模式注重轉換介面,將不吻合的介面適配對接,
橋接模式注重分離介面與其實作,支持多維度變化,
組合模式注重統一介面,將“一對多”的關系轉化為“一對一”的關系
裝飾者模式注重穩定介面,在此前提下為物件擴展功能,
外觀模式注重簡化介面,簡化組件系統與外部客戶程式的依賴關系,
享元模式注重保留介面,在內部使用共享技術對物件存盤進行優化,
代理模式注重假借介面,增加間接層來實作靈活控制,
從下篇文章就開始寫“行為型”設計模式,今天就到此結束了,
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/71324.html
標籤:C#
