C#設計模式系列:原型模式(Prototype)

libingql發表於2014-03-30

1、原型模式簡介

1.1>、定義

  原型模式(Prototype)用原型例項指定建立物件的種類,並且通過複製這些原型建立新的物件。

1.2>、使用頻率

  

1.3>、原型模式應用

  首先從實際生活來了解原型模式的由來,假設你有一份非常好的講義,你的朋友也想要一份,那麼怎麼辦?重新手抄一份?顯然不是,當然是用影印機影印一份來得方便、直接,並且準確性也高,這種用原型來複制而不是重新建立的思維方式就是原型模式的核心思想。

  Prototype Pattern也是一種建立型模式,它關注的是大量相同或相似物件的建立問題。應用原型模式就是建立一個原型,然後通過對原型來進行復制的方法,來產生一個和原型相同或相似的新物件,或者說用原型例項指定建立物件的種類,並且通過複製這些原型建立新的物件。

2、原型模式結構

2.1>、結構圖

2.2>、參與者

  原型模式參與者:

  ◊ Prototype:原型類,宣告一個Clone自身的介面;

  ◊ ConcretePrototype:具體原型類,實現一個Clone自身的操作。

  在原型模式中,Prototype通常提供一個包含Clone方法的介面,具體的原型ConcretePrototype使用Clone方法完成物件的建立。

3、原型模式結構實現

  Prototype.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.PrototypePattern.Structural
{
    /// <summary>
    /// The 'Prototype' abstract class
    /// </summary>
    public abstract class Prototype
    {
        private string _id;

        /// <summary>
        /// Constructor
        /// </summary>
        public Prototype(string id)
        {
            this._id = id;
        }

        /// <summary>
        /// Gets id
        /// </summary> 
        public string Id
        {
            get { return _id; }
        }

        public abstract Prototype Clone();
    }
}

  ConcretePrototype1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.PrototypePattern.Structural
{
    public class ConcretePrototype1 : Prototype
    {
        /// <summary>
        /// Constructor
        /// </summary>
        public ConcretePrototype1(string id)
            : base(id)
        {
        }

        /// <summary>
        /// Returns a shallow copy
        /// </summary>
        /// <returns></returns>
        public override Prototype Clone()
        {
            return (Prototype)this.MemberwiseClone();
        }
    }
}

  ConcretePrototype2.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.PrototypePattern.Structural
{
    public class ConcretePrototype2 : Prototype
    {
        /// <summary>
        /// Constructor
        /// </summary>
        public ConcretePrototype2(string id)
            : base(id)
        {
        }

        /// <summary>
        /// Returns a shallow copy
        /// </summary>
        /// <returns></returns>
        public override Prototype Clone()
        {
            return (Prototype)this.MemberwiseClone();
        }
    }
}

  Client.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using DesignPatterns.PrototypePattern.Structural;

namespace DesignPatterns.PrototypePattern
{
    class Client
    {
        static void Main(string[] args)
        {
            // Create two instances and clone each
            ConcretePrototype1 p1 = new ConcretePrototype1("I");
            ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone();
            Console.WriteLine("Cloned: {0}", c1.Id);

            ConcretePrototype2 p2 = new ConcretePrototype2("II");
            ConcretePrototype2 c2 = (ConcretePrototype2)p2.Clone();
            Console.WriteLine("Cloned: {0}", c2.Id);
        }
    }
}

  執行輸出:

Cloned: I
Cloned: II
請按任意鍵繼續. . .

4、原型模式實踐應用

 

  ColorPrototype.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.PrototypePattern.Practical
{
    /// <summary>
    /// The 'Prototype' abstract class
    /// </summary>
    public abstract class ColorPrototype
    {
        public abstract ColorPrototype Clone();
    }
}

  Color.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.PrototypePattern.Practical
{
    /// <summary>
    /// The 'ConcretePrototype' class
    /// </summary>
    public class Color : ColorPrototype
    {
        private int _red;
        private int _green;
        private int _blue;

        /// <summary>
        /// Constructor
        /// </summary>
        public Color(int red, int green, int blue)
        {
            this._red = red;
            this._green = green;
            this._blue = blue;
        }

        /// <summary>
        /// Create a shallow copy
        /// </summary>
        public override ColorPrototype Clone()
        {
            Console.WriteLine("Cloning color RGB: {0,3},{1,3},{2,3}", _red, _green, _blue);
            return this.MemberwiseClone() as ColorPrototype;
        }
    }
}

  ColorManager.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.PrototypePattern.Practical
{
    /// <summary>
    /// Prototype manager
    /// </summary>
    public class ColorManager
    {
        private Dictionary<string, ColorPrototype> _colors = new Dictionary<string, ColorPrototype>();

        /// <summary>
        /// Indexer
        /// </summary>
        public ColorPrototype this[string key]
        {
            get { return _colors[key]; }
            set { _colors.Add(key, value); }
        }
    }
}

  Client.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using DesignPatterns.PrototypePattern.Practical;

namespace DesignPatterns.PrototypePattern
{
    class Client
    {
        static void Main(string[] args)
        {
            ColorManager colormanager = new ColorManager();

            // Initialize with standard colors
            colormanager["red"] = new Color(255, 0, 0);
            colormanager["green"] = new Color(0, 255, 0);
            colormanager["blue"] = new Color(0, 0, 255);

            // User adds personalized colors
            colormanager["angry"] = new Color(255, 54, 0);
            colormanager["peace"] = new Color(128, 211, 128);
            colormanager["flame"] = new Color(211, 34, 20);

            // User clones selected colors
            Color color1 = colormanager["red"].Clone() as Color;
            Color color2 = colormanager["peace"].Clone() as Color;
            Color color3 = colormanager["flame"].Clone() as Color;
        }
    }
}

  執行輸出:

Cloning color RGB: 255,  0,  0
Cloning color RGB: 128,211,128
Cloning color RGB: 211, 34, 20
請按任意鍵繼續. . .

5、原型模式應用分析

  原型模式可以適用於以下情形:

  ◊ 當一個系統應該獨立於它的產品建立、構成和表示時;

  ◊ 當要例項化的類是在執行時刻指定時,例如通過動態裝載來建立一個類;

  ◊ 為了避免建立一個與產品類層次平行的工廠類層次時;

  ◊ 當一個類的例項只能有幾個不同狀態組合中的一種時。建立相應數目的原型並Clone它們可能比每次用合適的狀態手工例項化該類更方便一些。

  原型模式具有以下特點:

  ◊ 對客戶隱藏了具體的產品類,因此減少了客戶知道的名字的數目;

  ◊ 允許客戶只通過註冊原型例項就可以將一個具體產品類併入到系統中,客戶可以在執行時刻建立和刪除原型;

  ◊ 減少了子類的構造。原型模式是Clone一個原型而不是請求工廠方法建立一個,所以它不需要一個與具體產品類平行的Creator類層次;

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

  ◊ 產品類不需要非得有任何事先確定的等級結構,因為原型模式適用於任何的等級結構;

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

相關文章