創建型模式之原型模式


定義與特點

原型(Prototype)模式的定義如下:用一個已經創建的實例作為原型,通過復制該原型對象來創建一個和原型相同或相似的新對象。
在這里,原型實例指定了要創建的對象的種類。用這種方式創建對象非常高效,根本無須知道對象創建的細節。
例如,Windows 操作系統的安裝通常較耗時,如果復制就快了很多。在生活中復制的例子非常多,這里不一一列舉了。

結構與實現

由於 C# 提供了 ICloneable 接口,用 C# 實現原型模式很簡單。

模式的結構

原型模式包含以下主要角色:

  • 原型(Prototype):聲明一個克隆自身的接口,該角色一般有抽象類(Prototype)、接口(ICloneable)兩種實現方式(GOF使用的是抽象類,在C#中個人推薦使用接口)。
  • 具體原型類(ConcretePrototype):實現原型(抽象類或接口)的 Clone() 方法,它是可被復制的對象。
  • 訪問類(Client):使用具體原型類中的 Clone() 方法來復制新的對象。

使用接口作為Prototype時,其結構圖如圖所示(后面全部是接口方式的原型模式實現):

使用抽象類作為Prototype時,其結構圖如圖所示(來自GOF):

模式的實現

C# 中已經定義了 ICloneable 接口,具體原型類只要實現 ICloneable 接口就可實現對象的克隆(Object有 MemberwiseClone() 方法默認淺克隆),克隆是淺克隆還是深克隆取決於具體原型類 Clone() 的實現。其代碼如下:

//原型接口:該接口不需要自己定義,C#中已經定義好了
public interface ICloneable
{    
    Object Clone();
}

//抽象原型類
public abstract class Prototype
{
    public abstract Object Clone();
}

//具體原型類(接口方式)
public class ConcretePrototype : /*Prototype,*/ICloneable
{
    private int id;
    public int Id
    {
        get { return id; }
    }
    public ConcretePrototype(int id) 
    {
        this.id = id;
    }
    public Object Clone() 
    {
        return new ConcretePrototype(id);
    }

    //使用抽象原型類
    //public override Object Clone()
    //{
    //    //Object的默認克隆方式(淺克隆)
    //    return (Prototype)this.MemberwiseClone();
    //}
}

//訪問類,這里直接用的控制台的Program類
class Program
{
    static void Main(string[] args)
    {
        ConcretePrototype cp1 = new ConcretePrototype(1);
        ConcretePrototype cp2 = (ConcretePrototype)cp1.Clone();
        Console.WriteLine("cp1的Id為:{0}",cp1.Id);
        Console.WriteLine("cp2的Id為:{0}", cp2.Id);
        Console.ReadKey();
    }
}

運行結果:

cp1的Id為:1
cp2的Id為:1

應用場景

原型模式通常適用於以下場景:

  • 對象之間相同或相似,即只是個別的幾個屬性不同的時候。
  • 對象的創建過程比較麻煩,但復制比較簡單的時候。

擴展:帶原型管理器的原型模式

原型模式可擴展為帶原型管理器的原型模式,它在原型模式的基礎上增加了一個原型管理器 PrototypeManager 類。該類用 Dictionary(或HashMap) 保存多個復制的原型,Client 類可以通過管理器的 Get(String id) 方法從中獲取復制的原型。其結構如圖所示:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM