1. 程式人生 > >面向對象編程思想-原型模式

面向對象編程思想-原型模式

復雜度 pmo console 們的 get clone 一段 創建過程 產生

一、引言

相信大家都看過西遊記中孫悟空拔一根汗毛吹出千萬只猴子,可有沒有想過如果這些猴子一只一只的去經歷和孫悟空一樣的成長過程才能產生,這是何其的復雜和耗費精力啊?!類比在程序設計中,當需要創建多個相同的類的實例,這個創建過程又是極其復雜時,使用new操作符一個個去創建會增加內存開銷和程序復雜度。顯然,采用工廠方法模式是不適合的,沒必要每次都new一個相同的類的實例對象。建造者模式就更不用說了,是相同構建步驟創建不同的表示,一步步的創建也太麻煩了。那現在解決思路是 創建一個類的實例對象,如果後來再創建這樣的實例,可以通過對原來對象拷貝一份完成創建,這樣內存中就不要再重復創建相同的實例,減少內存開銷,達到類實例復用的效果。這其實就是今天我們要學習的原型模式

二、原型模式

在現實生活中也我們用復印機復印出多份相同的簡歷,電視中孫悟空吹出千萬只猴子等,都體現了原型模式思想,下面通過孫悟空的例子幫助我們理解原型模式

    //孫悟空打怪經歷類
    class WorkExperience:ICloneable
    {
        //時間段
        public string TimeArea{get;set;}
        //妖魔鬼怪
        public string Demon{get;set;}

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

 //淺復制 
     class ShallowMonkeyPrototype:ICloneable
    {
         private string Name;
         private string Age;
         private string Sex;

         private WorkExperience work;

         public ShallowMonkeyPrototype(string name)
         {
             
this.Name = name; work = new WorkExperience(); } //可以設置孫悟空的個人簡介 public void SetMonkeyPrototype(string age,string sex) { this.Age = age; this.Sex = sex; } //可以設置孫悟空的打怪經歷 public void SetWorkExperience(string timearea,string demon) { work.TimeArea = timearea; work.Demon = demon; } //顯示 public void Display() { Console.WriteLine("{0},{1},{2}",this.Name,this.Age,this.Sex); Console.WriteLine("打怪經歷:{0},{1}",work.TimeArea,work.Demon); } //MemberwiseClone方法(MSDN上的解釋) 創建一個新的對象,然後復制當前對象的非靜態字段的新對象創建一個淺表副本. //如果字段是值類型,則會執行字段的逐位副本。如果字段是引用類型,則引用對象被復制,但引用對象不是;因此原始對象及克隆引用了相同的對象 public object Clone() { return (object)this.MemberwiseClone(); } }

  //深復制
     class DeepMonkeyPrototype:ICloneable
    {
         private string Name;
         private string Age;
         private string Sex;

         private WorkExperience work;

         public DeepMonkeyPrototype(string name)
         {
             this.Name = name;
             work = new WorkExperience();
         }

         private DeepMonkeyPrototype(WorkExperience work)
         {
            this.work=(WorkExperience)work.Clone();
         }

         public void SetMonkeyPrototype(string age,string sex)
         {
             this.Age = age;
             this.Sex = sex;
         }

         public void SetWorkExperience(string timearea,string demon)
         {
             work.TimeArea = timearea;
             work.Demon = demon;
         }

         public void Display()
         {
             Console.WriteLine("{0},{1},{2}",this.Name,this.Age,this.Sex);
             Console.WriteLine("打怪經歷:{0},{1}",work.TimeArea,work.Demon);
         }

        public object Clone()
        {
            DeepMonkeyPrototype monkey = new DeepMonkeyPrototype(this.work);
            monkey.Name = this.Name;
            monkey.Age = this.Age;
            monkey.Sex = this.Sex;
            return monkey;
        }
    }

  class Program
    {
        static void Main(string[] args)
        {
            #region  //淺復制 客戶端調用
            ShallowMonkeyPrototype monkey1 = new ShallowMonkeyPrototype("孫悟空");
            monkey1.SetMonkeyPrototype("18", "");
            monkey1.SetWorkExperience("888-889", "白骨精");

            ShallowMonkeyPrototype monkey2 = (ShallowMonkeyPrototype)monkey1.Clone();
            monkey2.SetMonkeyPrototype("19", "");
            monkey2.SetWorkExperience("945-946", "黑熊怪");

            ShallowMonkeyPrototype monkey3 = (ShallowMonkeyPrototype)monkey1.Clone();
            monkey3.SetWorkExperience("1115-1116", "女兒國");
            #endregion
            #region  //深復制 客戶端調用
            //DeepMonkeyPrototype monkey1 = new DeepMonkeyPrototype("孫悟空");
            //monkey1.SetMonkeyPrototype("18", "男");
            //monkey1.SetWorkExperience("888-889","白骨精");

            //DeepMonkeyPrototype monkey2 = (DeepMonkeyPrototype)monkey1.Clone();
            //monkey2.SetWorkExperience("945-946", "黑熊怪");

            //DeepMonkeyPrototype monkey3 = (DeepMonkeyPrototype)monkey1.Clone();
            //monkey3.SetWorkExperience("1115-1116", "女兒國");
            #endregion
            monkey1.Display();
            monkey2.Display();
            monkey3.Display();
            Console.Read();
        }
    }

淺復制運行結果

技術分享

深復制運行結果

技術分享

通過上面demo的顯示,我們可以總結出

優點:原型模式隱藏了創建對象的復雜性,從一個對象再創建另一個可定制的對象,而不需要知道任何創建的細節

那淺復制和深復制又是怎麽回事,有什麽區別嗎?

1.通過兩次運行結果的對比,可以看出雖然淺復制時設置了孫悟空不同的打怪經歷,但是運行出來他們的經歷確實相同的,這是為什麽呢??通過分析得知

2.淺復制 被復制對象的所有變量都含有與原來對象相同的值,而所有對其他對象的引用都仍然指向原來的對象

3.深復制 把引用的對象的變量指向復制過的新對象,而不是原來被引用的對象

原型模式的缺點

1.每個類都必須有個克隆方法

2.配備克隆方法需要對類的功能通盤考慮,當一個類不支持串行化的間接對象,或者引用有循環結構的時候(啊啊啊。。。這一點其實我也不是很理解,先記一下在這裏,嘿嘿)

本文關於原型模式的學習就到這裏結束了,設計模式之創建型設計模式(關註對象的創建)通過前六篇設計模式文章的學習也告一段落,這種先定義,再附demo註釋,最後總結這種學習模式怎麽樣呢,歡迎指出您的看法和改進的地方。

文中如有不足,歡迎斧正,感謝您的閱讀。

面向對象編程思想-原型模式