乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      博客園 - 探索設(shè)計(jì)模式(六):原型模式(Prototype Pattern)

       心之所指 2006-01-23

      原型模式(Prototype Pattern

      ——探索設(shè)計(jì)模式系列之六

      Terrylee,20061

      概述

      在軟件系統(tǒng)中,有時候面臨的產(chǎn)品類是動態(tài)變化的,而且這個產(chǎn)品類具有一定的等級結(jié)構(gòu)。這時如果用工廠模式,則與產(chǎn)品類等級結(jié)構(gòu)平行的工廠方法類也要隨著這種變化而變化,顯然不大合適。那么如何封裝這種動態(tài)的變化?從而使依賴于這些易變對象的客戶程序不隨著產(chǎn)品類變化?

      意圖

      用原型實(shí)例指定創(chuàng)建對象的種類,并且通過拷貝這些原型創(chuàng)建新的對象。

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

      Prototype模式結(jié)構(gòu)圖

      生活中的例子

      Prototype模式使用原型實(shí)例指定創(chuàng)建對象的種類。新產(chǎn)品的原型通常是先于全部產(chǎn)品建立的,這樣的原型是被動的,并不參與復(fù)制它自己。一個細(xì)胞的有絲分裂,產(chǎn)生兩個同樣的細(xì)胞,是一個扮演主動角色復(fù)制自己原型的例子,這演示了原型模式。一個細(xì)胞分裂,產(chǎn)生兩個同樣基因型的細(xì)胞。換句話說,細(xì)胞克隆了自己。

      使用細(xì)胞分裂例子的Prototype模式對象圖

      原型模式解說

      我們考慮這樣一個場景,假定我們要開發(fā)一個調(diào)色板,用戶單擊調(diào)色板上任一個方塊,將會返回一個對應(yīng)的顏色的實(shí)例,下面我們看看如何通過原型模式來達(dá)到系統(tǒng)動態(tài)加載具體產(chǎn)品的目的。

      很自然,我們利用OO的思想,把每一種顏色作為一個對象,并為他們抽象出一個公用的父類,如下圖:

      實(shí)現(xiàn)代碼:

      public abstract class Color

      {

              public abstract void Display();

      }

      public class RedColor:Color

      {

          public override void Display()

          {

              Console.WriteLine("Red‘s RGB Values are:255,0,0");

          }

      }

      public class GreenColor:Color

      {

          public override void Display()

          {

              Console.WriteLine("Green‘s RGB Values are:0,255,0");

          }

      }

      客戶程序需要某一種顏色的時候,只需要創(chuàng)建對應(yīng)的具體類的實(shí)例就可以了。但是這樣我們并沒有達(dá)到封裝變化點(diǎn)的目的,也許你會說,可以使用工廠方法模式,為每一個具體子類定義一個與其等級平行的工廠類,那么好,看一下實(shí)現(xiàn):

      實(shí)現(xiàn)代碼:

      public abstract class ColorFactory

      {

          public abstract Color Create();

      }

      public class RedFactory:ColorFactory

      {

          public override Color Create()

          {

              return new RedColor();

          }

      }

      public class GreenFactory:ColorFactory

      {

          public override Color Create()

          {

              return new GreenColor();

          }

      }

      實(shí)現(xiàn)了這一步之后,可以看到,客戶程序只要調(diào)用工廠方法就可以了。似乎我們用工廠方法模式來解決是沒有問題的。但是,我們考慮的僅僅是封裝了new變化,而沒有考慮顏色的數(shù)量是不斷變化的,甚至可能是在程序運(yùn)行的過程中動態(tài)增加和減少的,那么用這種方法實(shí)現(xiàn),隨著顏色數(shù)量的不斷增加,子類的數(shù)量會迅速膨大,導(dǎo)致子類過多,顯然用工廠方法模式有些不大合適。

      進(jìn)一步思考,這些Color子類僅僅在初始化的顏色對象類別上有所不同。添加一個ColorTool這樣的類,來參數(shù)化的它的實(shí)例,而這些實(shí)例是由Color支持和創(chuàng)建的。我們讓ColorTool通過克隆或者拷貝一個Color子類的實(shí)例來創(chuàng)建新的Color,這個實(shí)例就是一個原型。如下圖所示:

      實(shí)現(xiàn)代碼:

      abstract class ColorPrototype

      {

          public abstract ColorPrototype Clone();

      }

      class ConcteteColorPrototype : ColorPrototype

      {

          private int _red, _green, _blue;

          public ConcteteColorPrototype(int red, int green, int blue)

          {

              this._red = red;

              this._green = green;

              this._blue = blue;

          }

           public override ColorPrototype Clone()

          {

              //實(shí)現(xiàn)淺拷貝

              return (ColorPrototype) this.MemberwiseClone();

          }

          public void Display(string _colorname)

          {

              Console.WriteLine("{0}‘s RGB Values are: {1},{2},{3}",

                  _colorname,_red, _green, _blue );

          }

      }

      class ColorManager

      { 

          Hashtable colors = new Hashtable();

          public ColorPrototype this[string name]

          {

              get

              {

                  return (ColorPrototype)colors[name];

              }

              set

              {

                  colors.Add(name,value);

              }

          }

      }

      現(xiàn)在我們分析一下,這樣帶來了什么好處?首先從子類的數(shù)目上大大減少了,不需要再為每一種具體的顏色產(chǎn)品而定一個類和與它等級平行的工廠方法類,而ColorTool則扮演了原型管理器的角色。再看一下為客戶程序的實(shí)現(xiàn):

      class App

      {

          public static void Main(string[] args)

          {

              ColorManager colormanager = new ColorManager();

              //初始化顏色

              colormanager["red"] = new ConcteteColorPrototype(255, 0, 0);

              colormanager["green"] = new ConcteteColorPrototype(0, 255, 0);

              colormanager["blue"] = new ConcteteColorPrototype(0, 0, 255);

              colormanager["angry"] = new ConcteteColorPrototype(255, 54, 0);

              colormanager["peace"] = new ConcteteColorPrototype(128, 211, 128);

              colormanager["flame"] = new ConcteteColorPrototype(211, 34, 20);

              //使用顏色

              string colorName = "red";

              ConcteteColorPrototype c1 = (ConcteteColorPrototype)colormanager[colorName].Clone();

              c1.Display(colorName);

              colorName = "peace";

              ConcteteColorPrototype c2 = (ConcteteColorPrototype)colormanager[colorName].Clone();

              c2.Display(colorName);

              colorName = "flame";

              ConcteteColorPrototype c3 = (ConcteteColorPrototype)colormanager[colorName].Clone();

              c3.Display(colorName);

              Console.ReadLine();

          }

      }

      可以看到,客戶程序通過注冊原型實(shí)例就可以將一個具體產(chǎn)品類并入到系統(tǒng)中,在運(yùn)行時刻,可以動態(tài)的建立和刪除原型。最后還要注意一點(diǎn),在上面的例子中,用的是淺表復(fù)制。如果想做深復(fù)制,需要通過序列化的方式來實(shí)現(xiàn)。經(jīng)過了上面的分析之后,我們再來思考下面的問題:

      1.為什么需要Prototype模式?

      引入原型模式的本質(zhì)在于利用已有的一個原型對象,快速的生成和原型對象一樣的實(shí)例。你有一個A的實(shí)例a:A a = new A();現(xiàn)在你想生成和car1一樣的一個實(shí)例b,按照原型模式,應(yīng)該是這樣:A b = a.Clone();而不是重新再new一個A對象。通過上面這句話就可以得到一個和a一樣的實(shí)例,確切的說,應(yīng)該是它們的數(shù)據(jù)成員是一樣的。Prototype模式同樣是返回了一個A對象而沒有使用new操作。

      2.引入Prototype模式帶來了什么好處?

      可以看到,引入Prototype模式后我們不再需要一個與具體產(chǎn)品等級結(jié)構(gòu)平行的工廠方法類,減少了類的構(gòu)造,同時客戶程序可以在運(yùn)行時刻建立和刪除原型。

      3Prototype模式滿足了哪些面向?qū)ο蟮脑O(shè)計(jì)原則?

      依賴倒置原則:上面的例子,原型管理器(ColorManager)僅僅依賴于抽象部分(ColorPrototype),而具體實(shí)現(xiàn)細(xì)節(jié)(ConcteteColorPrototype)則依賴與抽象部分(ColorPrototype),所以Prototype很好的滿足了依賴倒置原則。

      通過序列化實(shí)現(xiàn)深拷貝

      要實(shí)現(xiàn)深拷貝,可以通過序列化的方式。抽象類及具體類都必須標(biāo)注為可序列化的[Serializable],上面的例子加上深拷貝之后的完整程序如下:

      using System;

      using System.Collections;

      using System.IO;

      using System.Runtime.Serialization;

      using System.Runtime.Serialization.Formatters.Binary;

      [Serializable]

      abstract class ColorPrototype

      {

          public abstract ColorPrototype Clone(bool Deep);

      }

      [Serializable]

      class ConcteteColorPrototype : ColorPrototype

      {

          private int _red, _green, _blue;

          public ConcteteColorPrototype(int red, int green, int blue)

          {

              this._red = red;

              this._green = green;

              this._blue = blue;

          }

           public override ColorPrototype Clone(bool Deep)

          {

              if(Deep)

                  return CreateDeepCopy();

              else

                  return (ColorPrototype) this.MemberwiseClone();

          }

          //實(shí)現(xiàn)深拷貝

          public ColorPrototype CreateDeepCopy()

          {

              ColorPrototype colorPrototype;

              MemoryStream memoryStream = new MemoryStream();

              BinaryFormatter formatter = new BinaryFormatter();

              formatter.Serialize(memoryStream, this);

              memoryStream.Position = 0;

              colorPrototype = (ColorPrototype)formatter.Deserialize(memoryStream);

              return colorPrototype;

          }

          public ConcteteColorPrototype Create(int red,int green,int blue)

          {

              return new ConcteteColorPrototype(red,green,blue); 

          }

          public void Display(string _colorname)

          {

              Console.WriteLine("{0}‘s RGB Values are: {1},{2},{3}",

                  _colorname,_red, _green, _blue );

          }

      }

      class ColorManager

      { 

          Hashtable colors = new Hashtable();

           public ColorPrototype this[string name]

          {

              get

              {

                  return (ColorPrototype)colors[name];

              }

              set

              {

                  colors.Add(name,value);

              }

          }

      }

      class App

      {

          public static void Main(string[] args)

          {

              ColorManager colormanager = new ColorManager();

              //初始化顏色

              colormanager["red"] = new ConcteteColorPrototype(255, 0, 0);

              colormanager["green"] = new ConcteteColorPrototype(0, 255, 0);

              colormanager["blue"] = new ConcteteColorPrototype(0, 0, 255);

              colormanager["angry"] = new ConcteteColorPrototype(255, 54, 0);

              colormanager["peace"] = new ConcteteColorPrototype(128, 211, 128);

              colormanager["flame"] = new ConcteteColorPrototype(211, 34, 20);

              //使用顏色

              string colorName = "red";

              ConcteteColorPrototype c1 = (ConcteteColorPrototype)colormanager[colorName].Clone(false);

              c1.Display(colorName);

              colorName = "peace";

              ConcteteColorPrototype c2 = (ConcteteColorPrototype)colormanager[colorName].Clone(true);

              c2.Display(colorName);

              colorName = "flame";

              ConcteteColorPrototype c3 = (ConcteteColorPrototype)colormanager[colorName].Clone(true);

              c3.Display(colorName);

              Console.ReadLine();

          }

      }

      實(shí)現(xiàn)要點(diǎn)

      1.使用原型管理器,體現(xiàn)在一個系統(tǒng)中原型數(shù)目不固定時,可以動態(tài)的創(chuàng)建和銷毀,如上面的舉的調(diào)色板的例子。

      2.實(shí)現(xiàn)克隆操作,在.NET中可以使用Object類的MemberwiseClone()方法來實(shí)現(xiàn)對象的淺表拷貝或通過序列化的方式來實(shí)現(xiàn)深拷貝。

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

      效果

      1.它對客戶隱藏了具體的產(chǎn)品類,因此減少了客戶知道的名字的數(shù)目。

      2Prototype模式允許客戶只通過注冊原型實(shí)例就可以將一個具體產(chǎn)品類并入到系統(tǒng)中,客戶可以在運(yùn)行時刻建立和刪除原型。

      3.減少了子類構(gòu)造,Prototype模式是克隆一個原型而不是請求工廠方法創(chuàng)建一個,所以它不需要一個與具體產(chǎn)品類平行的Creater類層次。

      4Portotype模式具有給一個應(yīng)用軟件動態(tài)加載新功能的能力。由于Prototype的獨(dú)立性較高,可以很容易動態(tài)加載新功能而不影響老系統(tǒng)。

      5產(chǎn)品類不需要非得有任何事先確定的等級結(jié)構(gòu),因?yàn)?/SPAN>Prototype模式適用于任何的等級結(jié)構(gòu)

      6Prototype模式的最主要缺點(diǎn)就是每一個類必須配備一個克隆方法。而且這個克隆方法需要對類的功能進(jìn)行通盤考慮,這對全新的類來說不是很難,但對已有的類進(jìn)行改造時,不一定是件容易的事。

      適用性

      在下列情況下,應(yīng)當(dāng)使用Prototype模式:

      1.當(dāng)一個系統(tǒng)應(yīng)該獨(dú)立于它的產(chǎn)品創(chuàng)建,構(gòu)成和表示時;

      2.當(dāng)要實(shí)例化的類是在運(yùn)行時刻指定時,例如,通過動態(tài)裝載;

      3.為了避免創(chuàng)建一個與產(chǎn)品類層次平行的工廠類層次時;

      4.當(dāng)一個類的實(shí)例只能有幾個不同狀態(tài)組合中的一種時。建立相應(yīng)數(shù)目的原型并克隆它們可能比每次用合適的狀態(tài)手工實(shí)例化該類更方便一些。

      總結(jié)

      Prototype模式同工廠模式,同樣對客戶隱藏了對象的創(chuàng)建工作,但是,與通過對一個類進(jìn)行實(shí)例化來構(gòu)造新對象不同的是,原型模式是通過拷貝一個現(xiàn)有對象生成新對象的,達(dá)到了“隔離類對象的使用者和具體類型(易變類)之間的耦合關(guān)系”的目的。

      參考文獻(xiàn)

      《設(shè)計(jì)模式》(中文版)

      DesignPatternsExplained

      Java與模式》(閻宏 著)

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多