prototype詳解(轉)

          http://kid-li.cnblogs.com/archive/2006/05/18/403559.html
          好不容易才找到這個牛人寫的這個文章,向作者致敬。


          Prototype原型模式是一種創建型設計模式,它主要面對的問題是:“某些結構復雜的對象”的創建工作;由于需求的變化,這些對象經常面臨著劇烈的變化,但是他們卻擁有比較穩定一致的接口。感覺好像和前幾篇所說的設計模式有點分不清,下面我們先來回顧一下以前的幾種設計模式,予以區分,再來說說原型模式。

                 Singleton單件模式解決的問題是:實體對象個數問題(這個現在還不太容易混)

                 AbstractFactory抽象工廠模式解決的問題是:“一系列互相依賴的對象”的創建工作

                 Builder生成器模式解決的問題是:“一些復雜對象”的創建工作,子對象變化較頻繁,對算法相對穩定

                FactoryMethor工廠方法模式解決的問題是:某個對象的創建工作

                再回來看看今天的Prototype原型模式,它是用來解決“某些結構復雜的對象”的創建工作。現在看看,好象還是差不多。這個問題先放在這,我們先往下看Prototype原型模式。

                《設計模式》中說道:使用原型實例指定創建對象的種類,然后通過拷貝這些原型來創建新的對象。

                此時注意:原型模式是通過拷貝自身來創建新的對象,這一點和其他創建型模式不相同。好,我們再來看看原型模式的結構


                 這個結構說明原型模式的客戶端程序(ClientApp)是依賴于抽象(Prototype),而對象的具體實現也是依賴于抽象(Prototype)。符合設計模式原則中的依賴倒置原則——抽象不應依賴于具體實現,具體實現應依賴于抽象。

                 我們現在回來看看原型模式的實現,我定義了一個場景,一個人開這一輛車在一條公路上。現在這件事是確定的,但不確定的有幾點:1、人:姓名,性別,年齡;2車:什么牌子的;3公路:公路名字,長度,類型(柏油還是土路)。現在我們一個個實現。

                 先來實現人,定義一個抽象類,AbstractDriver,具體實現男性(Man)和女性(Women

          public abstract class AbstractDriver

              {

                  public AbstractDriver()

                  {

                      //

                      // TODO: 在此處添加構造函數邏輯

                      //

                  }

                  public string name;

                  public string sex;

                  public int age;

                  public abstract string drive();

                  public abstract AbstractDriver Clone();

              }

              public class Man:AbstractDriver

              {

                  public Man(string strName,int intAge)

                  {

                      sex = "Male";

                      name = strName;

                      age = intAge;

                  }

                  public override string drive()

                  {

                      return name + " is drive";

                  }

                  public override AbstractDriver Clone()

                  {

                      return (AbstractDriver)this.MemberwiseClone();

                  }

              }

              public class Women:AbstractDriver

              {

                  public Women(string strName,int intAge)

                  {

                      sex = "Female";

                      name = strName;

                      age = intAge;

                  }

                  public override string drive()

                  {

                      return name + " is drive";

                  }

                  public override AbstractDriver Clone()

                  {

                      return (AbstractDriver)this.MemberwiseClone();

                  }

              }

              注意:抽象代碼中有一個Clone的方法,個人認為這個方法是原型模式的一個基礎,因為前面講了原型模式是通過拷貝自身來創建新的對象。

                下面我們再來實現公路和汽車

                公路:

          public abstract class AbstractRoad

              {

                  public AbstractRoad()

                  {

                      //

                      // TODO: 在此處添加構造函數邏輯

                      //

                  }

                  public string Type;

                  public string RoadName;

                  public int RoadLong;

                  public abstract AbstractRoad Clone();

              }

              public class Bituminous:AbstractRoad    //柏油路

              {

                  public Bituminous(string strName,int intLong)

                  {

                      RoadName = strName;

                      RoadLong = intLong;

                      Type = "Bituminous";

                  }

                  public override AbstractRoad Clone()

                  {

                      return (AbstractRoad)this.MemberwiseClone();

                  }

              }

              public class Cement:AbstractRoad        //水泥路

              {

                  public Cement(string strName,int intLong)

                  {

                      RoadName = strName;

                      RoadLong = intLong;

                      Type = "Cement";

                  }

                  public override AbstractRoad Clone()

                  {

                      return (AbstractRoad)this.MemberwiseClone();

                  }

              }

             

              汽車:

              public abstract class AbstractCar

              {

                  public AbstractCar()

                  {

                      //

                      // TODO: 在此處添加構造函數邏輯

                      //

                  }

                  public string OilBox;

                  public string Wheel;

                  public string Body;

                  public abstract string Run();

                  public abstract string Stop();

                  public abstract AbstractCar Clone();

              }

              public class BMWCar:AbstractCar

              {

                  public BMWCar()

                  {

                      OilBox = "BMW's OilBox";

                      Wheel = "BMW's Wheel";

                      Body = "BMW's body";

                  }

                  public override string Run()

                  {

                      return "BMW is running";

                  }

                  public override string Stop()

                  {

                      return "BMW is stoped";

                  }

                  public override AbstractCar Clone()

                  {

                      return (AbstractCar)this.MemberwiseClone();

                  }

              }

              public class BORACar:AbstractCar

              {

                  public BORACar()

                  {

                      OilBox = "BORA's OilBox";

                      Wheel = "BORA's Wheel";

                      Body = "BORA's Body";

                  }

                  public override string Run()

                  {

                      return "BORA is running";

                  }

                  public override string Stop()

                  {

                      return "BORA is stoped";

                  }

                  public override AbstractCar Clone()

                  {

                      return (AbstractCar)this.MemberwiseClone();

                  }

              }

              public class VolvoCar:AbstractCar

              {

                  public VolvoCar()

                  {

                      OilBox = "Volvo's OilBox";

                      Wheel = "Volvo's Wheel";

                      Body = "Volvo's Body";

                  }

                  public override string Run()

                  {

                      return "Volvo is running";

                  }

                  public override string Stop()

                  {

                      return "Volvo is stoped";

                  }

                  public override AbstractCar Clone()

                  {

                      return (AbstractCar)this.MemberwiseClone();

                  }

              }

              然后我們再來看看場景,我們定義一個Manage類,在這個場景中有一個人,一輛車和一條公路,代碼實現如下:

          class Manage

              {

                  public AbstractCar Car;

                  public AbstractDriver Driver;

                  public AbstractRoad Road;

                  public void Run(AbstractCar car,AbstractDriver driver,AbstractRoad road)

                  {

                      Car = car.Clone();

                      Driver = driver.Clone();

                      Road = road.Clone();

                  }

              }

              可以看到,在這個代碼中,場景只是依賴于那幾個抽象的類來實現的。最后我們再來實現一下客戶代碼,比如我現在要一輛Volvo車,一個叫“Anli”的女司機,在一條叫“Road1”、長1000的柏油路上。

                  static void Main(string[] args)

                  {

                      Manage game = new Manage();

                      game.Run(new VolvoCar(),new Women("Anli",18),new Bituminous("Road1",1000));

                      Console.Write("CarRun:" + game.Car.Run() + ""n");

                      Console.Write("DriverName:" + game.Driver.name + ""n");

                      Console.Write("DriverSex:" + game.Driver.sex + ""n");

                      Console.Write("RoadName:" + game.Road.RoadName + ""n");

                      Console.Write("RoadType:" + game.Road.Type + ""n");

                      Console.Write("CarStop:" + game.Car.Stop() + ""n");

                      Console.Read();

                  }

              運行的結果是:

              CarRun:Volvo is running

          DriverName:Anli

          DriverSex:Female

          RoadName:Road1

          RoadType:Bituminous

          CarStop:Volvo is stoped

          如果我現在想換成BORA車,讓我(kid-li)開,在一個水泥馬路上,我們只要更改Main函數中Run的實參。

          game.Run(new BORACar(),new Man("kid-li",24),new Cement("Road1",1000));

          運行結果是:

          CarRun:BORA is running

          DriverName:kid-li

          DriverSex:Male

          RoadName:Road1

          RoadType:Cement

          CarStop:BORA is stoped

          這樣,經過簡單的更改,可以實現實現細節的變化。

          現在我們再來看看原型模式的幾個要點:

          1、Prototype模式同樣用于隔離類對象的使用者和具體類型(易變類)之間的耦合關系,它同樣要求這些“易變類”擁有“穩定的接口”。

          2、Prototype模式對于“如何創建易變類的實體對象”采用“原型克隆”的方法來實現,它使得我們可以非常靈活地動態創建“擁有某些穩定接口”的新對象——所需工作僅僅是注冊一個新類的對象(即原型),然后在任何需要的地方不斷地Clone。

          3、Prototype模式中的Clone方法可以利用Object類的MemberwiseClone()或者序列化來實現深拷貝。

          這里面我們再來說說淺拷貝和深拷貝。我想對于Prototype模式是很重要的。我覺得淺拷貝和深拷貝的關鍵區別是對于引用對象的拷貝。例如我們有一個類Class1,

          public class Class1

          {

              int a;

              int[] b;

          }

          我們用淺拷貝實現了兩個對象c1和c2,對于c1.a和c2.a,他們所有的內存空間是不一樣的,但是c1.b和c2.b,由于它們是引用類型,在淺拷貝時只是拷貝了一個地址給b成員,實際上c1.b和c2.b指向同一塊內存。

          但如果我們用深拷貝,c1.b和c2.b指向的是不同的內存地址。那又如何實現深拷貝呢?我們可以利用序列化和反序列化來實現。

          對于淺拷貝和深考貝的問題,我的同事TerryLee曾寫過一篇文章《小議.NET中的對象拷貝》,我在這就不贅述了。

          posted on 2007-11-29 17:38 liujg 閱讀(308) 評論(1)  編輯  收藏

          評論

          # re: prototype詳解(轉) 2008-12-21 21:01 hehei

          郁悶,.NET的!,JAVA里面有MemberwiseClone這個方法么。怎么用JAVA搞原型模式呢?  回復  更多評論   


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          <2008年12月>
          30123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          導航

          統計

          常用鏈接

          留言簿(1)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          相冊

          收藏夾

          boddiy

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 明水县| 全椒县| 方城县| 常州市| 海林市| 松潘县| 凌云县| 高阳县| 延安市| 五华县| 乐陵市| 仙居县| 深州市| 宣威市| 蓬溪县| 永嘉县| 图木舒克市| 舟曲县| 夏津县| 措勤县| 凌源市| 息烽县| 斗六市| 定远县| 贵定县| 山丹县| 宁武县| 明溪县| 东乡县| 安阳市| 南丰县| 辉县市| 荆州市| 三门峡市| 万宁市| 临沭县| 长海县| 连山| 江孜县| 米易县| 沛县|