設(shè)計模式系列-代理模式

      今天下班,同事們無聊中又聊到了食堂(怎么寫食堂?吃貨?。。?,辦公區(qū)離食堂遠(yuǎn)的同事老阮在大家你一句我一句的誘惑下,終于忍不住了決定不管在遠(yuǎn)也要找時間去嘗嘗,但是因為上班不順路也不是很方便,就委托我們宿舍的老李同志幫忙第二天先去開卡充值,熱心腸的老李當(dāng)然不會拒絕嘍。

成都創(chuàng)新互聯(lián)服務(wù)項目包括渭城網(wǎng)站建設(shè)、渭城網(wǎng)站制作、渭城網(wǎng)頁制作以及渭城網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,渭城網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到渭城省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

      1、模擬場景

      有了這個前奏今天的主題就當(dāng)然又有了,那么首先我們用代碼來實現(xiàn)上面的功能,首先來分析一下上面的場景:

      ①我們需要對卡片充值,所以需要一個卡片類,代碼如下:

  1. /// <summary> 
  2.     /// 卡片類 
  3.     /// </summary> 
  4.     public class Card  
  5.     {  
  6.         //卡片名稱 
  7.         private string cardName = string.Empty;  
  8.         public string CardName  
  9.         {  
  10.             get 
  11.             {  
  12.                 return cardName;  
  13.             }  
  14.             set 
  15.             {  
  16.                 cardName = value;  
  17.             }  
  18.         }  
  19.         //構(gòu)造方法 
  20.         public Card() { }  
  21.         public Card(string cName)  
  22.         {  
  23.             cardName = cName;  
  24.         }  
  25.     }  
       ②接下來就是路遠(yuǎn)的老阮,他的工卡需要去激活,代碼如下:
	
  1. /// <summary> 
  2.    /// 老阮 
  3.    /// </summary> 
  4.    public class MrRuan  
  5.    {  
  6.        //他有一個工卡 
  7.        private Card myCard = new Card("mrRuan");  
  8.  
  9.        public Card MyCard  
  10.        {  
  11.            get 
  12.            {  
  13.                return myCard;  
  14.            }  
  15.        }  
  16.    }  
      ③ 接下來就是激活卡片當(dāng)然要去柜臺了,記得在單例模式中已經(jīng)將這個柜臺類實現(xiàn)了,那么我們就拿來用現(xiàn)成的吧,代碼如下:
  1. /// <summary> 
  2.     /// 柜臺類 
  3.     /// </summary> 
  4.     public sealed class Counter  
  5.     {  
  6.         //在第一次調(diào)用類成員時,初始化唯一實例 
  7.         private static readonly Counter instance = new Counter();  
  8.  
  9.         private Counter()  
  10.         {  
  11.         }  
  12.  
  13.         //返回類型實例屬性 
  14.         public static Counter Instance  
  15.         {  
  16.             get 
  17.             {  
  18.                 return instance;  
  19.             }  
  20.         }  
  21.  
  22.         //激活工卡方法 
  23.         public void ActivationCard(Card card)  
  24.         {  
  25.             //激活工卡的過程 
  26.             Console.WriteLine("{0}的工卡激活成功!",card.CardName);  
  27.         }  
  28.     }  
          ④ 再就是幫助老軟第二天去激活卡片的老李,因為老李需要去激活卡片,所以包含激活卡片的操作,代碼如下:
	
  1. /// <summary> 
  2.    /// 熱心腸的老李 
  3.    /// </summary> 
  4.    public class MrLi  
  5.    {  
  6.        //激活工卡方法 
  7.        public void ActivationCard(Card card)  
  8.        {  
  9.            Counter.Instance.ActivationCard(card);  
  10.        }  
  11.    }  
          ⑤ 類型都抽象出來之后當(dāng)然就是第二天去激活卡片啦,主函數(shù)調(diào)用代碼如下:
	
  1. static void Main(string[] args)  
  2.       {  
  3.             //實例化老阮 
  4.             MrRuan ruan = new MrRuan();  
  5.  
  6.             //實例化老李 
  7.             MrLi li = new MrLi();  
  8.  
  9.             //將卡片給老李,老李負(fù)責(zé)去激活 
  10.             li.ActivationCard(ruan.MyCard);  
  11.        }  
              仔細(xì)想了一下,這樣一來老李也就成了柜臺開卡的代理人了,以后別人也可以委托他去幫忙激活卡片了,這不就是活生生的代理模式嗎?

        這時你要問了,那代理模式具體的定義是什么呀?到底什么是代理模式下?別著急繼續(xù)往下看吧。

      2、代理模式

           代理(Proxy)模式定義:為其他對象提供一種代理以控制對這個對象的訪問。

           這時我們發(fā)現(xiàn)了多了一個接口ICounter,那么實現(xiàn)了接口的代理類與具體類的代碼如下:

  1. /// <summary> 
  2.     /// 柜臺類也就是具體類提供的功能規(guī)則 
  3.     /// </summary> 
  4.     public interface ICounter  
  5.     {  
  6.         void ActivationCard(Card card);  
  7.     }  
  8.  /// <summary> 
  9.     /// 熱心腸的老李 
  10.     /// </summary> 
  11.     public class MrLi : ICounter  
  12.     {  
  13.         //激活工卡方法 
  14.         public void ActivationCard(Card card)  
  15.         {  
  16.             Counter.Instance.ActivationCard(card);  
  17.         }  
  18.     }  
  19.  
  20.       
  21.     /// <summary> 
  22.     /// 柜臺類 
  23.     /// </summary> 
  24.     public sealed class Counter : ICounter  
  25.     {  
  26.         //在第一次調(diào)用類成員時,初始化唯一實例 
  27.         private static readonly Counter instance = new Counter();  
  28.  
  29.         private Counter()  
  30.         {  
  31.         }  
  32.  
  33.         //返回類型實例屬性 
  34.         public static Counter Instance  
  35.         {  
  36.             get 
  37.             {  
  38.                 return instance;  
  39.             }  
  40.         }  
  41.  
  42.         //激活工卡方法 
  43.         public void ActivationCard(Card card)  
  44.         {  
  45.             //激活工卡的過程 
  46.             Console.WriteLine("{0}的工卡激活成功!",card.CardName);  
  47.         }  
  48.     }  
        那么這個接口有什么用呢?

       在面向?qū)ο笤O(shè)計中,對象之間需要進行交互和通信。例如:上面的代理類MrLi調(diào)用了具體類柜臺類counter的激活卡片的方法(ActiviationCard),那么這個時候代理類MrLi不在代理counter柜臺的激活卡片功能了,而是去另一個counterNew的柜臺去激活,但是counterNew柜臺激活卡片的方法是(CounterActiviationCard),怎么辦?我們需要去修改調(diào)用counter的類,那么如何降低耦合性呢?當(dāng)然就是將接口和實現(xiàn)分離開來,這樣代理間和柜臺對象之間的依賴就是基于接口,而不是實現(xiàn)!

       例如:目前MrLi與counter之間的調(diào)用如下:

  1. /// <summary> 
  2.    /// 熱心腸的老李 
  3.    /// </summary> 
  4.    public class MrLi   
  5.    {  
  6.        //激活工卡方法 
  7.        public void ActivationCard(Card card)  
  8.        {  
  9.            Counter.Instance.ActivationCard(card);  
  10.        }  
  11.    }  
         那么如果需要加入新的柜臺類(counterNew),它的激活方法叫(CounterActivationCard),代碼如下:
  1. /// <summary> 
  2.    /// 新的柜臺類 
  3.    /// </summary> 
  4.    public sealed class NewCounter   
  5.    {  
  6.        //在第一次調(diào)用類成員時,初始化唯一實例 
  7.        private static readonly NewCounter instance = new NewCounter();  
  8.  
  9.        private NewCounter()  
  10.        {  
  11.        }  
  12.  
  13.        //返回類型實例屬性 
  14.        public static NewCounter Instance  
  15.        {  
  16.            get 
  17.            {  
  18.                return instance;  
  19.            }  
  20.        }  
  21.  
  22.        //激活工卡方法 
  23.        public void CounterActivationCard(Card card)  
  24.        {  
  25.            //激活工卡的過程 
  26.            Console.WriteLine("{0}的工卡激活成功!", card.CardName);  
  27.        }  
  28.    }  
      這樣兩個類就緊密的耦合在一起了,若Counter類改變,那么MrLi類也不得不改變,這時我們?nèi)绻胧褂眯碌墓衽_類(NewCounter),也需要修改調(diào)用者本身。

      所以我們需要使用接口分離實現(xiàn)。代碼如下:

  1. /// <summary> 
  2.    /// 柜臺類也就是具體類提供的功能規(guī)則 
  3.    /// </summary> 
  4.    public interface ICounter  
  5.    {  
  6.        void ActivationCard(Card card);  
  7.    }  
  8.  
  9.     /// <summary> 
  10.    /// 熱心腸的老李 
  11.    /// </summary> 
  12.    public class MrLi : ICounter  
  13.    {  
  14.        //激活工卡方法 
  15.        public void ActivationCard(Card card)  
  16.        {  
  17.            Counter.Instance.ActivationCard(card);  
  18.        }  
  19.    }  
  20.  
  21.      
  22.    /// <summary> 
  23.    /// 柜臺類 
  24.    /// </summary> 
  25.    public sealed class Counter : ICounter  
  26.    {  
  27.        //在第一次調(diào)用類成員時,初始化唯一實例 
  28.        private static readonly Counter instance = new Counter();  
  29.  
  30.        private Counter()  
  31.        {  
  32.        }  
  33.  
  34.        //返回類型實例屬性 
  35.        public static Counter Instance  
  36.        {  
  37.            get 
  38.            {  
  39.                return instance;  
  40.            }  
  41.        }  
  42.  
  43.        //激活工卡方法 
  44.        public void ActivationCard(Card card)  
  45.        {  
  46.            //激活工卡的過程 
  47.            Console.WriteLine("{0}的工卡激活成功!",card.CardName);  
  48.        }  
  49.    }  
  50.  
  51.    /// <summary> 
  52.    /// 新的柜臺類 
  53.    /// </summary> 
  54.    public sealed class NewCounter : ICounter  
  55.    {  
  56.        //在第一次調(diào)用類成員時,初始化唯一實例 
  57.        private static readonly NewCounter instance = new NewCounter();  
  58.  
  59.        private NewCounter()  
  60.        {  
  61.        }  
  62.  
  63.        //返回類型實例屬性 
  64.        public static NewCounter Instance  
  65.        {  
  66.            get 
  67.            {  
  68.                return instance;  
  69.            }  
  70.        }  
  71.  
  72.        //激活工卡方法 
  73.        public void ActivationCard(Card card)  
  74.        {  
  75.            //激活工卡的過程 
  76.            Console.WriteLine("{0}的工卡激活成功!", card.CardName);  
  77.        }  
  78.    }  
       有了接口的約束,所有柜臺類都遵循了這個約束將激活卡片的方法統(tǒng)一成(ActivationCard),那么在將來切換對象的時候都可以以一種統(tǒng)一的調(diào)用方式去無縫的卻換。

      這時細(xì)心的朋友還會說,Mr.Li的ActivationCard方法中調(diào)用的是具體的counter類型如果換成Newcounter,還是要去修改它的代碼,你現(xiàn)在只能是不用去修改調(diào)用方法了而已,想的好,還記得我們當(dāng)時的工廠模式嗎?它的好處不就是降低耦合嗎?為什么不用?

      那么加入工廠類(CounterProvider),在修改一下MrLi的調(diào)用使它的調(diào)用依賴于抽象接口而不是具體的實現(xiàn),代碼如下:

  1. /// <summary> 
  2.     /// 熱心腸的老李 
  3.     /// </summary> 
  4.     public class MrLi : ICounter  
  5.     {  
  6.         //激活工卡方法 
  7.         public void ActivationCard(Card card)  
  8.         {  
  9.             ICounter counter = CounterProvider.GetCounter();  
  10.             counter.ActivationCard(card);  
  11.         }  
  12.     }  
  13.  
  14.     /// <summary> 
  15.     /// 柜臺類工廠 
  16.     /// </summary> 
  17.     public class CounterProvider  
  18.     {  
  19.         public static ICounter GetCounter()  
  20.         {  
  21.             ICounter counter = null;  
  22.             //從配置文件確定實例化那個柜臺類 
  23.             if (ReadConfig)  
  24.             {  
  25.                 counter = Counter.Instance;  
  26.             }  
  27.             else 
  28.             {  
  29.                 counter = NewCounter.Instance;  
  30.             }  
  31.         }  
  32.     }  
        這樣我們就徹底的實現(xiàn)了代理模式,并且詮釋了如何使用接口的好處和靈活組合模式與靈活理解模式與使用。

      3、應(yīng)用場景

      那么代理模式的幾種使用場景我們來看一看:

      ① 遠(yuǎn)程代理:為一個對象在不同地址空間提供局部代表。這樣可以隱藏一個對象存在于不同地址空間的事實,例如:老阮(MrRuan)在地點A,老李在地點B,餐廳柜臺也在地點B,那么老李和老軟住在一起(都在地點A?。敲蠢侠罹褪遣蛷d(地點B)在老軟與老李住處(地點A)的代表。

      ② 虛擬代理:是根據(jù)需要創(chuàng)建開銷很大的對象。通過它來存放實例化需要很長時間的真是對象,例如:老阮(MrRuan)在地點A,到餐廳柜臺(地點B),因為距離遠(yuǎn)卻是很費勁,而老李剛好在這里(地點B)上班,所以讓老李去辦是很可行的辦法。(不太恰當(dāng))

      ③ 安全代理:用來控制真是對象訪問時的權(quán)限,例如:老阮跟餐廳的柜臺MM剛分手不方便去辦理,所以需要借助老李去完成事項的辦理。

      ④ 智能代理:是指當(dāng)調(diào)用真是的對象時,代理去處理另外一些事情,例如:老李幫助老阮辦理卡片激活時,順便說說老阮的好話,讓她倆能夠和好。

文章名稱:設(shè)計模式系列-代理模式
標(biāo)題路徑:http://muchs.cn/article24/ipjeje.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站建設(shè)用戶體驗、品牌網(wǎng)站設(shè)計、網(wǎng)站改版、網(wǎng)站營銷定制開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運營