<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      Fork me on GitHub

      代理模式(Proxy)

      1.1.1 摘要

           今天是父親節(jié),首先祝爸爸父親節(jié)快樂身體健康,隨著互聯(lián)網(wǎng)飛速的發(fā)展,現(xiàn)在許多軟件系統(tǒng)都提供跨網(wǎng)絡(luò)和系統(tǒng)的應(yīng)用,但在跨網(wǎng)絡(luò)和系統(tǒng)應(yīng)用時(shí),作為系統(tǒng)開發(fā)者并不希望客戶直接訪問系統(tǒng)中的對(duì)象。其中原因很多考慮到系統(tǒng)安全和性能因素,這時(shí)候聰明的開發(fā)者想到了在客戶端和系統(tǒng)端添加一層中間層----代理層,也是即將要介紹的代理模式。

       

      • 定義

      代理模式(Proxy)為另一個(gè)對(duì)象提供一個(gè)替身或占位符以控制對(duì)這個(gè)對(duì)象的訪問,簡(jiǎn)而言之就是用一個(gè)對(duì)象來代表另一個(gè)對(duì)象。

      • 意圖

      提供其他對(duì)象一個(gè)代理或占位符,來控制該對(duì)象的訪問權(quán)限。

      • 動(dòng)機(jī)

            為什么我們要控制對(duì)象的訪問權(quán)限呢?其中一個(gè)原因是通過控制來延遲對(duì)象的創(chuàng)建和實(shí)例化,直到真正需要使用該對(duì)象才進(jìn)行創(chuàng)建和實(shí)例化。由于一些對(duì)象創(chuàng)建和實(shí)例化需要占用大量系統(tǒng)資源,但我們并不能確定用戶一定會(huì)調(diào)用該對(duì)象,所以通過延遲對(duì)象實(shí)例化來減緩系統(tǒng)資源的消耗。例如文檔編輯器如word,我們可以在里面插入鏈接、圖片等,但是并不是我們每次打開word時(shí)都有創(chuàng)建和實(shí)例化這些對(duì)象,特別是實(shí)例化圖片對(duì)象很消耗資源,而且我們有必要實(shí)例化所有圖片嗎?當(dāng)我們?cè)诓榭磜ord時(shí),只是看到其中的一部分,所以沒有必要實(shí)例化所以資源,當(dāng)我們看下一頁時(shí)再實(shí)例化也不遲。

      • 結(jié)構(gòu)圖clip_image001

      圖1代理模式結(jié)構(gòu)圖

      1.1.2 正文

            軟件系統(tǒng)設(shè)計(jì)可以提供本地或遠(yuǎn)程的方法,隨著互聯(lián)網(wǎng)的發(fā)展特別是WebService技術(shù)的提出,使得更多軟件系統(tǒng)都提供遠(yuǎn)程方法調(diào)用。當(dāng)我們?cè)L問網(wǎng)絡(luò)上一臺(tái)計(jì)算機(jī)的資源時(shí),我們正在跨越網(wǎng)絡(luò)障礙,跨越網(wǎng)絡(luò)障礙有時(shí)候是非常復(fù)雜,因?yàn)橐_保數(shù)據(jù)安全可靠地傳輸。如果真的要我們都去解決那些復(fù)雜網(wǎng)絡(luò)問題,那么我估計(jì)程序員們瘋了。還好代理模式(Proxy)幫我們解決了其中的一些問題----WebService技術(shù)。

           現(xiàn)在讓我們通過一個(gè)簡(jiǎn)單的加減乘除程序?yàn)槔f明什么是代理模式(Proxy)和如何實(shí)現(xiàn)。

           現(xiàn)在我們服務(wù)器端提供計(jì)算方法,分別定義計(jì)算類Math和代理類MathProxy。然后我們的客戶端通過調(diào)研MathProxy來間接用Math類的計(jì)算方法。

      /// <summary>
      /// Define a interface, make proxy and subject
      /// have the same methods.
      /// </summary>
      public interface IMath
      {
          /// <summary>
          /// Calc methods.
          /// </summary>
          /// <param name="x"></param>
          /// <param name="y"></param>
          /// <returns></returns>
          double Add(double x, double y);
          double Sub(double x, double y);
          double Mul(double x, double y);
          double Div(double x, double y);
      }
      
      
      /// <summary>
      /// A proxy class.
      /// </summary>
      public class MathProxy : IMath
      {
          /// <summary>
          /// MathProxy has a Math's reference.
          /// </summary>
          private Math _math;
      
          public MathProxy()
          {
              AppDomain ad =
                  AppDomain.CreateDomain("MathDomain", null, null);
      
              /// Create a Math object.
              ObjectHandle obj = ad.CreateInstance(
                  "Gof.DesignPattern.Proxy.Math",
                  "Gof.DesignPattern.Proxy.Math.Math");
      
              this._math = obj.Unwrap() as Math;
          }
      
          #region IMath 成員
      
          public double Add(double x, double y)
          {
              return _math.Add(x, y);
          }
      
          public double Sub(double x, double y)
          {
              return _math.Sub(x, y);
          }
      
          public double Mul(double x, double y)
          {
              return _math.Mul(x, y);
          }
      
          public double Div(double x, double y)
          {
              return _math.Div(x, y);
          }
      
          #endregion
      
      }
      
      /// <summary>
      /// Due to Math inherits MarshalByRefObject
      /// so the class supports remoting.
      /// </summary>
      public class Math : MarshalByRefObject, IMath
      {
          #region IMath 成員
      
          public double Add(double x, double y)
          {
              return x + y;
          }
      
          public double Sub(double x, double y)
          {
              return x - y;
          }
      
          public double Mul(double x, double y)
          {
              return x * y;
          }
      
          public double Div(double x, double y)
          {
              if (y == 0)
              {
                  return 0;
              }
              
              return x / y;
          }
      
          #endregion
      }
      
      
      public class Program
      {
          static void Main(string[] args)
          {
              
              // Create math proxy.
              MathProxy prox = new MathProxy();
      
              //
              Console.WriteLine(prox.Add(2, 6));
              Console.WriteLine(prox.Sub(88, 2));
              Console.WriteLine(prox.Mul(22, 55));
              Console.WriteLine(prox.Div(5, 0));
      
              Console.ReadKey();
          }
      
      }
       proxy1

      圖2網(wǎng)絡(luò)中代理模式

            現(xiàn)在我們實(shí)現(xiàn)了Math類的代理模式,使得客戶端通過MathProxy代理類來調(diào)用Math提供的Add()、Sub()、Mul() 和Div() 方法。

            但細(xì)心的你肯定發(fā)現(xiàn)問題了,我的程序根本沒有提供夸網(wǎng)絡(luò)的實(shí)現(xiàn),最多就是夸應(yīng)用程序的調(diào)用,的確我并沒有實(shí)現(xiàn)跨網(wǎng)絡(luò)的調(diào)用,那我們?cè)撊绾螌?shí)現(xiàn)跨網(wǎng)絡(luò)呢?還記得我們前面介紹的WebService技術(shù)嗎?要實(shí)現(xiàn)跨網(wǎng)絡(luò)可以選擇使用WebService來公開我們Math類中的方法,讓客戶端添加Math類的Web引用,從而WebService充當(dāng)了代理角色。

           我們前面提到的圖片延遲加載的例子,這其中也是體現(xiàn)了代理模式的思想。例如我們?cè)诓榭匆恍┚W(wǎng)頁之后,我們的瀏覽器會(huì)保留一些網(wǎng)頁的信息,從而加快下次網(wǎng)頁加載的速度。現(xiàn)在讓我們通過一個(gè)簡(jiǎn)單WinForm圖片加載器程序說明:

           圖片加載器首先查看我們本地是否已經(jīng)存在要加載的圖片,如果存在就直接加載圖片,如果不存在它會(huì)到網(wǎng)絡(luò)中下載圖片然后進(jìn)行加載。

      proxy2

      圖3圖片加載器界面

            由于時(shí)間的關(guān)系我們已經(jīng)把界面設(shè)計(jì)好了,現(xiàn)在我們要完成的是點(diǎn)擊Test Image Proxy按鈕的邏輯,首先我們圖片加載器會(huì)查看本地是否已經(jīng)存在圖片,如果不存在就到網(wǎng)絡(luò)上加載我們需要的圖片就OK了。

      /// <summary>
      /// The image proxy
      /// If we have dowload the picture in local,
      /// then the program would get it, otherwise
      /// the program would get the picture in internet.
      /// </summary>
      private class ImageProxy
      {
          private static Image _image = null;
      
          private int _width = 123;
          private int _height = 154;
          private bool _retrieving = false;
      
          public int Width
          {
              get { return _image == null ? _width : _image.Width; }
          }
      
          public int Height
          {
              get { return _image == null ? _height : _image.Height; }
          }
      
          /// <summary>
          /// Gets the image.
          /// </summary>
          public Image Image
          {
              get 
              {
                  if (_image != null)
                  {
                      return _image;
                  }
                  else
                  {
                      if (!_retrieving)
                      {
                          _retrieving = true;
                          //// Initialize a thread.
                          Thread retrieveThread = new Thread(
                              new ThreadStart(RetrieveImage));
                          //// Start thread.
                          retrieveThread.Start();
                      }
                  }
                  //// If the picture in local, we get it directly.
                  return PlaceHolderImage(); 
              }
          }
      
          /// <summary>
          /// Places the holder image.
          /// Get the picture in local.
          /// </summary>
          /// <returns></returns>
          public Image PlaceHolderImage()
          {
              return new Bitmap(System.Reflection.Assembly.GetExecutingAssembly().
                  GetManifestResourceStream(this.GetType().Namespace.ToString() + ".googlefathersday.jpg"));
          }
      
      
          /// <summary>
          /// Retrieves the image.
          /// Get the picture in internet.
          /// </summary>
          public void RetrieveImage()
          {
              string url = @"http://www.google.com.hk/logos/2011/fathersday11-hp.jpg";
      
              HttpWebRequest request = HttpWebRequest.Create(url) as HttpWebRequest;
              HttpWebResponse response = request.GetResponse() as HttpWebResponse;
      
              _image = Image.FromStream(response.GetResponseStream());
      
          }
      }

           上面我們完成了點(diǎn)擊加載的邏輯,我們提供一個(gè)圖片加載代理ImageProxy類,然后分別提供本地加載和網(wǎng)絡(luò)加載功能PlaceHolderImage()方法和RetrieveImage()方法,PlaceHolderImage()方法把圖片嵌入到程序中,而RetrieveImage()到網(wǎng)絡(luò)中加載圖片。

         proxy3
      proxy4

      圖4圖片加載效果

          這里我們使用了灰色和彩色圖片分別表示本地和網(wǎng)絡(luò)加載效果,現(xiàn)在我們通過代理模式(Proxy)完成了圖片延遲加載的效果。

          我覺得《HeadFirst設(shè)計(jì)模式》中的糖果機(jī)代理模式比較有趣,現(xiàn)在也讓我們通過C#來實(shí)現(xiàn)糖果機(jī)代理模式。

          問題描述:現(xiàn)在有些分布在不同地方的糖果機(jī)(類似自動(dòng)售賣機(jī)),我們要通過網(wǎng)絡(luò)方式獲得糖果機(jī)中的糖果數(shù)量和糖果機(jī)的狀態(tài)。

          現(xiàn)在我們要添加三個(gè)項(xiàng)目分別是:GumballState.Machine、Host和Client(其中Host是WebService),在GumballState.Machine里面我們定義糖果機(jī)售賣邏輯和狀態(tài),Host把我們定義售賣機(jī)方法通過網(wǎng)絡(luò)形式發(fā)布,Client通過添加Web引用間接調(diào)用GumballState.Machine中的方法。

      proxy5

      圖5糖果機(jī)程序

       

          首先我們GumballState.Machine類添加五個(gè)方法分別是:StartWithQuarters()、InsertQuarter()、TurnCrank()、EjectQuarter()和GetReport()。

      • StartWithQuarters()方法初始化糖果數(shù)量和修改糖果機(jī)狀態(tài)。
      /// <summary>
      /// Starts the with quarters.
      /// Calc the current qty and set machine state.
      /// </summary>
      /// <param name="cnt">The CNT.</param>
      public void StartWithQuarters(int cnt)
      {
          this._cnt = cnt;
          if (this._cnt > 0)
          {
              this._state = GumballMachineState.NoQuarter;
          }
      }
      • InsertQuarter()方法判斷用戶付款操作和修改糖果機(jī)狀態(tài)。
      /// <summary>
      /// Inserts the quarter.
      /// The user inserts money
      /// </summary>
      public void InsertQuarter()
      {
          switch (this._state)
          {
              case (GumballMachineState.HasQuarter):
                  this._logMsg.Append("You can't insert another quarter\n");
                  return;
      
              case (GumballMachineState.NoQuarter):
                  this._state = GumballMachineState.HasQuarter;
                  this._logMsg.Append("You inserted a quarter\n");
                  return;
      
              case (GumballMachineState.SoldOut):
                  this._logMsg.Append("You can't insert a quarter, the machine is sold out\n");
                  return;
      
              case (GumballMachineState.Sold):
                  this._logMsg.Append("Please wait, we're already giving you a gumball\n");
                  return;
      
          }
      }
      • TurnCrank()方法判斷用戶確定購買操作和修改糖果機(jī)狀態(tài)。
        /// <summary>
        /// Turns the crank.
        /// The user presses "OK" button to get gumball.
        /// </summary>
        public void TurnCrank()
        {
            if (this._state == GumballMachineState.SoldOut)
            {
                this._logMsg.Append("You turned, but there are no gumballs\n");
            }
            else if (this._state == GumballMachineState.HasQuarter)
            {
                this._logMsg.Append("You turned please wait...\n");
                this._state = GumballMachineState.Sold;
                this.Dispense();
            }
            else if (this._state == GumballMachineState.NoQuarter)
            {
                this._logMsg.Append("You turned but there's no quarter\n");
            }
            else
            {
                this._logMsg.Append("Turning twice doesn't get you another gumball!\n");
            }
        }
      • EjectQuarter()方法判斷用戶退款操作和修改糖果機(jī)狀態(tài)。
      /// <summary>
      /// Ejects the quarter.
      /// The user cancels order and get money back.
      /// </summary>
      public void EjectQuarter()
      {
          switch (this._state)
          {
              case (GumballMachineState.HasQuarter):
                  this._state = GumballMachineState.NoQuarter;
                  this._logMsg.Append("Quarter returned\n");
                  return;
      
              case (GumballMachineState.NoQuarter):
                  this._state = GumballMachineState.HasQuarter;
                  this._logMsg.Append("You haven't inserted a quarter\n");
                  return;
      
              case (GumballMachineState.SoldOut):
                  this._logMsg.Append("Sorry, you already turned the crank\n");
                  return;
      
              case (GumballMachineState.Sold):
                  this._logMsg.Append("You can't eject, you haven't inserted a quarter yet\n");
                  return;
      
          }
      }
      • GetReport()方法返回糖果機(jī)銷售量和狀態(tài)給管理者。
      /// <summary>
      /// Gets the report.
      /// </summary>
      /// <returns></returns>
      public string GetReport()
      {
          StringBuilder result = new StringBuilder();
          result.Append("\nMighty Gumball, Inc.");
          result.Append("\n.NET3.5-enabled Standing Gumball Model #2104\n");
          result.Append("Inventory: " + this._cnt + " gumball");
          if (this._cnt != 1) result.Append("s");
      
          result.Append("\nMachine is ");
          if (_state == GumballMachineState.SoldOut)
          {
              result.Append("sold out");
          }
          else if (_state == GumballMachineState.NoQuarter)
          {
              result.Append("waiting for quarter");
          }
          else if (_state == GumballMachineState.HasQuarter)
          {
              result.Append("waiting for turn of crank");
          }
          else if (_state == GumballMachineState.Sold)
          {
              result.Append("delivering a gumball");
          }
          result.Append("\n");
      
          string ret = this._logMsg.ToString() + "\n" + result.ToString();
          this._logMsg = new StringBuilder();
      
          return ret.ToString();
      }

          接著我們通過WebService把以上方法通過網(wǎng)絡(luò)形式發(fā)布,然后我們?cè)诳蛻舳颂砑觲eb引用來間接調(diào)用GumballState.Machine類中方法。

      clip_image001

      proxy7

      圖6客戶端添加web引用

         現(xiàn)在我們完成了服務(wù)器端的功能了,接下來我們通過控制臺(tái)應(yīng)用程序作為客戶端調(diào)用服務(wù)器端公開的方法。

      class Program
      {
          static void Main()
          {
              // Create proxy object
              GumballMachineClient proxy = new GumballMachineClient();
      
              proxy.StartWithQuarters(5);
              proxy.InsertQuarter();
              proxy.TurnCrank();
      
              Console.WriteLine(proxy.GetReport());
      
              proxy.InsertQuarter();
              proxy.EjectQuarter();
              proxy.TurnCrank();
      
              Console.WriteLine(proxy.GetReport());
      
              proxy.InsertQuarter();
              proxy.TurnCrank();
              proxy.InsertQuarter();
              proxy.TurnCrank();
              proxy.EjectQuarter();
      
              Console.WriteLine(proxy.GetReport());
      
              proxy.InsertQuarter();
              proxy.InsertQuarter();
              proxy.TurnCrank();
              proxy.InsertQuarter();
              proxy.TurnCrank();
              proxy.InsertQuarter();
              proxy.TurnCrank();
      
              Console.WriteLine(proxy.GetReport());
      
              // Wait for user
              Console.ReadKey();
          }
      }

      圖7客戶端調(diào)用web方法

            現(xiàn)在我們通過控制臺(tái)應(yīng)用程序添加web引用之后,來調(diào)用GumballState.Machine類中方法,我們終于正在實(shí)現(xiàn)了一個(gè)跨網(wǎng)絡(luò)的應(yīng)用程序調(diào)用,WebService充當(dāng)了proxy的角色,而且?guī)臀覀兘鉀Q了很多網(wǎng)絡(luò)的問題使得我們實(shí)現(xiàn)跨網(wǎng)絡(luò)程序十分方便。

      1.1.3 總結(jié)

         代理模式(Proxy)根據(jù)種類不同,效果也不盡相同:

      • 遠(yuǎn)程(Remote)代理:為一個(gè)位于不同的地址空間的對(duì)象提供一個(gè)局域代表對(duì)象。這個(gè)不同的地址空間可以是在本機(jī)器中,也可是在另一臺(tái)機(jī)器中。遠(yuǎn)程代理又叫做大使(Ambassador)。好處是系統(tǒng)可以將網(wǎng)絡(luò)的細(xì)節(jié)隱藏起來,使得客戶端不必考慮網(wǎng)絡(luò)的存在。客戶完全可以認(rèn)為被代理的對(duì)象是局域的而不是遠(yuǎn)程的,而代理對(duì)象承擔(dān)了大部份的網(wǎng)絡(luò)通訊工作。由于客戶可能沒有意識(shí)到會(huì)啟動(dòng)一個(gè)耗費(fèi)時(shí)間的遠(yuǎn)程調(diào)用,因此客戶沒有必要的思想準(zhǔn)備。
      • 虛擬(Virtual)代理(圖片延遲加載的例子):根據(jù)需要?jiǎng)?chuàng)建一個(gè)資源消耗較大的對(duì)象,使得此對(duì)象只在需要時(shí)才會(huì)被真正創(chuàng)建。使用虛擬代理模式的好處就是代理對(duì)象可以在必要的時(shí)候才將被代理的對(duì)象加載;代理可以對(duì)加載的過程加以必要的優(yōu)化。當(dāng)一個(gè)模塊的加載十分耗費(fèi)資源的情況下,虛擬代理的好處就非常明顯。
      • Copy-on-Write代理:虛擬代理的一種。把復(fù)制(克隆)拖延到只有在客戶端需要時(shí),才真正采取行動(dòng)。
      • 智能引用(Smart Reference)代理:當(dāng)一個(gè)對(duì)象被引用時(shí),提供一些額外的操作,比如將對(duì)此對(duì)象調(diào)用的次數(shù)記錄下來等。

       

           代理模式(Proxy)VS 裝飾者(Decorator)

           意圖:它們都提供間接訪問對(duì)象層,都保存被調(diào)用對(duì)象的引用。

           代理模式(Proxy):為另一個(gè)對(duì)象提供一個(gè)替身或占位符以控制對(duì)這個(gè)對(duì)象的訪問,簡(jiǎn)而言之就是用一個(gè)對(duì)象來代表另一個(gè)對(duì)象。

          裝飾者(Decorator):動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé),就增加功能來說,Decorator模式比生成子類更為靈活,它避免了類爆炸問題,像裝飾者(Decorator),代理模式(Proxy)組成一個(gè)對(duì)象并提供相同的接口,但代理模式并不關(guān)心對(duì)象動(dòng)態(tài)職能的增減。

          在代理模式(Proxy)中Subject定義了主要的功能,而且Proxy根據(jù)Subject提供功能控制對(duì)象的訪問權(quán)限。在裝飾者(Decorator)中Component只是提供了其中的一些功能,需要通過裝飾鏈動(dòng)態(tài)給對(duì)象增加職能。

       

      代理模式(Proxy)例子源程序

      posted @ 2011-06-19 20:43  JK_Rush  閱讀(29174)  評(píng)論(11)    收藏  舉報(bào)
      主站蜘蛛池模板: 五月天久久综合国产一区二区| 中文字幕国产精品一二区| 国产亚洲精品AA片在线爽| 一 级做人爱全视频在线看| 人妻无码| 丰满少妇在线观看网站| 国产亚洲精品久久综合阿香 | 国产女人叫床高潮大片| 国产360激情盗摄全集| 精品中文人妻在线不卡| 国产一区二区三区禁18| 白白色发布永久免费观看视频 | 久久国产乱子精品免费女| 亚洲日韩久热中文字幕| 少妇无套内谢免费视频| 国产精品福利片在线观看| 日本黄漫动漫在线观看视频| 欧美丰满熟妇性xxxx| 国产丝袜在线精品丝袜不卡| 久久久www免费人成精品| 婷婷六月天在线| 亚洲大尺度无码无码专线| 综合久久av一区二区三区| 成人午夜在线观看日韩| 日本大片在线看黄a∨免费| 亚洲情A成黄在线观看动漫尤物 | 亚洲高清国产成人精品久久| 国产免费爽爽视频| 国产初高中生粉嫩无套第一次| 蓝山县| 国产乱码精品一区二区三| 99久久婷婷国产综合精品青草漫画| 日韩内射美女人妻一区二区三区| 欧洲亚洲成av人片天堂网| 国产综合色产在线视频欧美| 亚洲高清免费在线观看| 她也色tayese在线视频| 亚洲综合精品香蕉久久网| 麻豆最新国产AV原创精品| а∨天堂一区中文字幕| 国产一二三五区不在卡|