設計模式:原型模式


原型模式的定義:

  原型模式:使用原型實例指定待創建對象的類型,並且通過復制這個原型來創建新的對象。

原型模式的結構:

  原型模式主要包含3個角色:

    

    (1)Prototype(抽象原型類):聲明克隆方法的接口,是所有具體原型類的公共父類,它可是抽象類也可以是接口,甚至可以是具體實現類。

    (2)ConcretePrototype(具體原型類):它實現抽象原型類中聲明的克隆方法,在克隆方法中返回自己的一個克隆對象。

    (3)Client(客戶端):在客戶類中,讓一個原型對象克隆自身從而創建一個新的對象。

深克隆與淺克隆:

    淺克隆:當原型對象被復制時,只復制它本身和其中包含的值類型的成員變量,而引用類型的成員變量並沒有復制。

    

    深克隆:除了對象本身被復制外,對象所包含的所有成員變量也將被復制。

    

原型模式的實現:

  在使用某OA系統時,有些崗位的員工發現他們每周的工作都大同小異,因此在填寫工作周報時很多內容都是重復的,為了提高工作周報的創建效率,大家迫切地希望有一種機制能夠快速創建相同或者相似的周報,包括創建周報的附件。試使用原型模式對該OA系統中的工作周報創建模塊進行改進。

 

  

 

  代碼如下:

  WeeklyLog:周報類

    [Serializable]
    public class WeeklyLog
    {
        public Attachment Attachment { get; set; }
        public string Name { get; set; }
        public string Date { get; set; }
        public string Content { get; set; }
        /// <summary>
        /// 使用MemberwiseClone()實現淺克隆
        /// </summary>
        /// <returns></returns>
        //public WeeklyLog Clone()
        //{
        //    return (WeeklyLog)this.MemberwiseClone();
        //}

        //使用序列化的方式實現深克隆
        public WeeklyLog Clone()
        {
            WeeklyLog clone = null;
            FileStream fs = new FileStream("temp.dat", FileMode.Create);
            BinaryFormatter formatter = new BinaryFormatter();
            try
            {
                formatter.Serialize(fs, this);
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to Serialize . Reason :" + e.Message);
                throw;
            }
            finally
            {
                fs.Close();
            }
            FileStream fs1 = new FileStream("temp.dat", FileMode.Open);
            BinaryFormatter formatter1 = new BinaryFormatter();
            try
            {
                clone = (WeeklyLog)formatter.Deserialize(fs1);//反序列化
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to deserialize. Reasion:" + e.Message);
                throw;
            }
            finally
            {
                fs1.Close();
            }

            return clone;
        }
    }

  Attachmeht:附件類

    [Serializable]
    public class Attachment
    {
        public string Name { get; set; }


        public void Dowmload()
        {
            Console.WriteLine("下載附件,文件名為{0}", Name);
        }
    }

客戶端代碼:

        static void Main(string[] args)
        {
            WeeklyLog log, log_new;
            log = new WeeklyLog();
            Attachment attchment = new Attachment();
            log.Attachment = attchment;
            log_new = log.Clone();
            System.Console.WriteLine("周報是否相同?{0}",log==log_new ? "":"");
            System.Console.WriteLine("附件是否相同?{0}",log.Attachment == log_new.Attachment ? "":"");
            System.Console.ReadKey();
        }

原型管理器:

  將多個原型對象存儲在一個集合中供客戶端使用,它是一個專門負責克隆對象的工廠,其中定義了一個集合用於存儲原型對象,如果需要某個原型對象的一個克隆,可以通過復制集合中對應的原型對象來獲得。

  

  代碼如下:

    public class PrototypeManager
    {
        Hashtable ht = new Hashtable();
        public PrototypeManager()
        {
            ht.Add("A", new ConcretePrototypeA());
            ht.Add("B", new ConcretePrototypeB());
        }

        public void Add(string key, Prototype prototype)
        {
            ht.Add(key, prototype);
        }

        public Prototype Get(string key)
        {
            Prototype clone = null;
            clone = ((Prototype)ht[key]).Clone();
            return clone;
        }
    }


    public abstract class Prototype
    {
        public abstract Prototype Clone();
    }

    public class ConcretePrototypeA : Prototype
    {
        public override Prototype Clone()
        {
            return (ConcretePrototypeA)this.MemberwiseClone();
        }
    }

    public class ConcretePrototypeB : Prototype
    {
        public override Prototype Clone()
        {
            return (ConcretePrototypeB)this.MemberwiseClone();
        }
    }

    在實際開發當中,可以將PrototypeManager設計為單例模式,確保系統中有且只有一個PrototypeManager對象,有利於節省系統資源,還可以更好的對原型管理器對象進行控制。。。。

原型模式的優缺點:

  優點:(1):當創建對象的實例較為復雜的時候,使用原型模式可以簡化對象的創建過程,通過復制一個已有的實例可以提高實例的創建效率。

     (2):擴展性好,由於原型模式提供了抽象原型類,在客戶端針對抽象原型類進行編程,而將具體原型類寫到配置文件中,增減或減少產品對原有系統都沒有影響。

     (3):原型模式提供了簡化的創建結構,工廠方法模式常常需要有一個與產品類等級結構相同的工廠等級結構,而原型模式不需要這樣,圓形模式中產品的復制是通過封裝在類中的克隆方法實現的,無需專門的工廠類來創建產品。

     (4):可以使用深克隆方式保存對象的狀態,使用原型模式將對象復制一份並將其狀態保存起來,以便在需要的時候使用(例如恢復到歷史某一狀態),可輔助實現撤銷操作。

  缺點:(1):需要為每一個類配置一個克隆方法,而且該克隆方法位於類的內部,當對已有類進行改造的時候,需要修改代碼,違反了開閉原則。

     (2):在實現深克隆時需要編寫較為復雜的代碼,而且當對象之間存在多重簽到引用時,為了實現深克隆,每一層對象對應的類都必須支持深克隆,實現起來會比較麻煩。

原型模式的適用環境:

  1:創建新對象成本較大(例如初始化時間長,占用CPU多或占太多網絡資源),新對象可以通過復制已有對象來獲得,如果相似對象,則可以對其成員變量稍作修改。

  2:系統要保存對象的狀態,而對象的狀態很小。

  3:需要避免使用分層次的工廠類來創建分層次的對象,並且類的實例對象只有一個或很少的組合狀態,通過復制原型對象得到新實例可以比使用構造函數創建一個新實例更加方便。


免責聲明!

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



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