1. 程式人生 > >模式設計 建立型 Prototype

模式設計 建立型 Prototype


名稱 Prototype
結構 o_prototype.bmp
意圖 用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。
適用性
  • 當要例項化的類是在執行時刻指定時,例如,通過動態裝載;或者
  • 為了避免建立一個與產品類層次平行的工廠類層次時;或者
  • 當一個類的例項只能有幾個不同狀態組合中的一種時。建立相應數目的原型並克隆它們可能比每次用合適的狀態手工例項化該類更方便一些。


Code Example
namespace Prototype_DesignPattern
{
    using System;

    // Objects which are to work as prototypes must be based on classes which 
    
// are derived from the abstract prototype class
    abstract class AbstractPrototype 
    {
        abstract public AbstractPrototype CloneYourself();
    }


    // This is a sample object
    class MyPrototype : AbstractPrototype 
    {
        override public AbstractPrototype CloneYourself()
        {
            return
 ((AbstractPrototype)MemberwiseClone());
        }

        // lots of other functions go here!
    }


    // This is the client piece of code which instantiate objects
    
// based on a prototype. 
    class Demo 
    {
        private AbstractPrototype internalPrototype;

        public void SetPrototype(AbstractPrototype thePrototype)
        {
            internalPrototype = thePrototype;            
        }


        public void SomeImportantOperation()
        {
            // During Some important operation, imagine we need
            
// to instantiate an object - but we do not know which. We use
            
// the predefined prototype object, and ask it to clone itself. 

            AbstractPrototype x;
            x = internalPrototype.CloneYourself();
            // now we have two instances of the class which as as a prototype
        }

    }


    ///<summary>
    
///    Summary description for Client.
    
///</summary>

    public class Client
    {
        public static int Main(string[] args)
        {                        
            Demo demo = new Demo();
            MyPrototype clientPrototype = new MyPrototype();
            demo.SetPrototype(clientPrototype);
            demo.SomeImportantOperation();

            return 0;
        }

    }

}

C#對原型模式的支援

在C#裡面,我們可以很容易的通過Clone()方法實現原型模式。任何類,只要想支援克隆,必須實現C#中的ICloneable介面。ICloneable介面中有一Clone方法,可以在類中複寫實現自定義的克隆方法。克隆的實現方法有兩種:淺拷貝(shallow copy)與深拷貝(deep copy)。
五、 淺拷貝與深拷貝

下面給出淺拷貝與深拷貝的兩個例子,例子使用了ICloneable介面。C#中的陣列是引用型的變數,我們通過陣列來進行演示:

淺拷貝:

using System;

class ShallowCopy : ICloneable
{
  public int[] v = {1,2,3};

  public Object Clone()
  {
    return this.MemberwiseClone();
  }


  public void Display()
  {
    foreach(int i in v)
      Console.Write( i + ", ");
    Console.WriteLine();
  }

}


class Client
{
  public static void Main()
  {
    ShallowCopy sc1 = new ShallowCopy();
    ShallowCopy sc2 = (ShallowCopy)sc1.Clone();
    sc1.v[0] = 9;

    sc1.Display();
    sc2.Display();
  }

}


ShallowCopy物件實現了一個淺拷貝,因此當對sc1進行克隆時,其欄位v並沒有克隆,這導致sc1與sc2的欄位v都指向了同一個v,因此,當修改了sc1的v[0]後,sc2的v[0]也發生了變化。

深拷貝:

using System;

class DeepCopy : ICloneable
{
  public int[] v = {1,2,3};

  // 預設建構函式
  public DeepCopy()
  {
  }


  // 供Clone方法呼叫的私有建構函式
  private DeepCopy(int[] v)
  {
    this.v = (int[])v.Clone();
  }


  public Object Clone()
  {
    // 構造一個新的DeepCopy物件,構造引數為
    
// 原有物件中使用的 v 
    return new DeepCopy(this.v);
  }


  public void Display()
  {
    foreach(int i in v)
      Console.Write( i + ", ");
    Console.WriteLine();
  }

}


class Client
{
  public static void Main()
  {
    DeepCopy dc1 = new DeepCopy();
    DeepCopy dc2 = (DeepCopy)dc1.Clone();
    dc1.v[0] = 9;

    dc1.Display();
    dc2.Display();
  }

}


這次在克隆的時候,不但克隆物件本身,連裡面的陣列欄位一併克隆。因此,最終打印出來的dc1與dc2不同。

Prototype模式的優點與缺點 
Prototype模式的優點包括 

1、Prototype模式允許動態增加或減少產品類。由於建立產品類例項的方法是產批類內部具有的,因此增加新產品對整個結構沒有影響。 

2、Prototype模式提供了簡化的建立結構。工廠方法模式常常需要有一個與產品類等級結構相同的等級結構,而Prototype模式就不需要這樣。 

3、Portotype模式具有給一個應用軟體動態載入新功能的能力。由於Prototype的獨立性較高,可以很容易動態載入新功能而不影響老系統。 

4、產品類不需要非得有任何事先確定的等級結構,因為Prototype模式適用於任何的等級結構。 


Prototype模式的缺點: 

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