国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

設計模式(16)---原型模式

2019-11-14 16:18:35
字體:
來源:轉載
供稿:網友

一、定義

原型模式:用原型實例指定創建對象的種類,并且通過拷貝這些原型創建新的對象。

解釋:有一個設計非常復雜的對象,如果需要得到多個這樣對象的時候,可以先創建一個原型對象,然后使用原型對象clone出新的對象,從而實現減少內存消耗和類實例復用的目的。

 

二、UML類圖及基本代碼

基本代碼:

abstract class PRototype    {        private string id;        public string ID        {            get { return id; }        }        public Prototype(string id)        {            this.id = id;        }        public abstract Prototype Clone();    }    class ConcretePrototype : Prototype    {        public ConcretePrototype(string id)            : base(id)        { }        public override Prototype Clone()        {            return (Prototype)this.MemberwiseClone();        }    }

客戶端調用:

ConcretePrototype cp1 = new ConcretePrototype("a");            ConcretePrototype cp2 = (ConcretePrototype)cp1.Clone();

 

三、具體實例

編寫一個簡歷,包含姓名、性別、年齡、工作經歷等,然后復制多份進行顯示。

實例代碼及運行結果:

class Program    {        static void Main(string[] args)        {            Resume resume1 = new Resume("tom");            resume1.SetPersonInfo("man", "17");            resume1.SetWorkExperience("1980-1990", "xx company");            Resume resume2 = (Resume)resume1.Clone();            resume2.SetWorkExperience("1990-2000", "yy company");            Resume resume3 = (Resume)resume1.Clone();            resume3.SetPersonInfo("man", "19");            resume1.Display();            resume2.Display();            resume3.Display();            Console.Read();        }    }    class Resume : ICloneable    {        private string name;        private string sex;        private string age;        private string timeArea;        private string company;        public Resume(string name)        {            this.name = name;        }        public void SetPersonInfo(string sex, string age)        {            this.sex = sex;            this.age = age;        }        public void SetWorkExperience(string timeArea, string company)        {            this.timeArea = timeArea;            this.company = company;        }        public void Display()        {            Console.WriteLine("{0} {1} {2}", name, sex, age);            Console.WriteLine("workexperience:{0} {1}", timeArea, company);        }        public object Clone()        {            return (object)this.MemberwiseClone();        }    }
View Code

 

實例延伸:

上述實例總MemberwiseClone()方法是:如果字段是值類型,則對該字段執行逐位復制,如果字段是引用類型,則復制引用,但不復制引用的對象。這稱之為淺拷貝,被復制對象的所有變量都含有與原來對象相同的值,而所有的對其他對象的引用都仍然指向原來的對象。接下來,將工作經歷單獨拿出來作為一個類在簡歷類中引用。如下:

class Program    {        static void Main(string[] args)        {            Resume resume1 = new Resume("tom");            resume1.SetPersonInfo("man", "17");            resume1.SetWorkExperience("1980-1990", "xx company");            Resume resume2 = (Resume)resume1.Clone();            resume2.SetWorkExperience("1990-2000", "yy company");            Resume resume3 = (Resume)resume1.Clone();            resume1.SetWorkExperience("2000-2010", "zz company");            resume1.Display();            resume2.Display();            resume3.Display();            Console.Read();        }    }    class WorkExperience    {        private string timeArea;        public string TimeArea        {            get { return timeArea; }            set { timeArea = value; }        }        private string company;        public string Company        {            get { return company; }            set { company = value; }        }    }    class Resume : ICloneable    {        private string name;        private string sex;        private string age;        private WorkExperience work;        public Resume(string name)        {            this.name = name;            work = new WorkExperience();        }        public void SetPersonInfo(string sex, string age)        {            this.sex = sex;            this.age = age;        }        public void SetWorkExperience(string timeArea, string company)        {            work.TimeArea = timeArea;            work.Company = company;        }        public void Display()        {            Console.WriteLine("{0} {1} {2}", name, sex, age);            Console.WriteLine("workexperience:{0} {1}", work.TimeArea, work.Company);        }        public object Clone()        {            return (object)this.MemberwiseClone();        }    }
View Code

結果如下:

分析:工作經歷是有3段,但運行結果只顯示一段。由此可見淺拷貝對于類中引用對象的復制并不成功。

 

四、概念講解

淺拷貝:當對象的字段值被拷貝時,字段引用的對象不會被拷貝。例如,如果一個對象有一個指向字符串的字段,并且我們對該對象做了一個淺拷貝,那么這兩個對象將引用同一個字符串。

深拷貝:對對象實例中字段引用的對象也進行拷貝,如果一個對象有一個指向字符串的字段,并且我們對該對象進行了深拷貝的話,那么我們將創建一個對象和一個新的字符串,新的對象將引用新的字符串。

也就是說,執行深拷貝創建的新對象和原來對象不會共享任何東西,改變一個對象對另外一個對象沒有任何影響,而執行淺拷貝創建的新對象與原來對象共享成員,改變一個對象,另外一個對象的成員也會改變。

 

五、實例改進

同樣是上述的實例,對于有引用字段的,本例使用深拷貝,代碼如下:

class Program    {        static void Main(string[] args)        {            Resume resume1 = new Resume("tom");            resume1.SetPersonInfo("man", "17");            resume1.SetWorkExperience("1980-1990", "xx company");            Resume resume2 = (Resume)resume1.Clone();            resume2.SetWorkExperience("1990-2000", "yy company");            Resume resume3 = (Resume)resume1.Clone();            resume1.SetWorkExperience("2000-2010", "zz company");            resume1.Display();            resume2.Display();            resume3.Display();            Console.Read();        }    }    class WorkExperience:ICloneable //實現ICloneable接口    {        private string timeArea;        public string TimeArea        {            get { return timeArea; }            set { timeArea = value; }        }        private string company;        public string Company        {            get { return company; }            set { company = value; }        }        public object Clone()        {            return (object)this.MemberwiseClone();        }    }    class Resume : ICloneable    {        private string name;        private string sex;        private string age;        private WorkExperience work;        public Resume(string name)        {            this.name = name;            work = new WorkExperience();        }        private Resume(WorkExperience work)        {            this.work = (WorkExperience)work.Clone();//提供Clone方法調用的私有構造函數,以便克隆工作經歷的數據        }        public void SetPersonInfo(string sex, string age)        {            this.sex = sex;            this.age = age;        }        public void SetWorkExperience(string timeArea, string company)        {            work.TimeArea = timeArea;            work.Company = company;        }        public void Display()        {            Console.WriteLine("{0} {1} {2}", name, sex, age);            Console.WriteLine("workexperience:{0} {1}", work.TimeArea, work.Company);        }        public object Clone()        {            Resume obj = new Resume(this.work);//調用私有構造方法,讓工作經歷克隆完成,然后在給這個簡歷對象的相關字段賦值,最終返回一個深拷貝的對象             obj.name = this.name;            obj.sex = this.sex;            obj.age = this.age;            return obj;        }    }
View Code

運行結果:

 

六、優缺點及適用場景

優點:

1)原型模式向客戶隱藏了創建新實例的復制性

2)允許動態增加或者減少產品類。

缺點:

1)每個類必須配備一個克隆方法

2)對于新建的類使用拷貝很容易,對于已有的類進行拷貝時,特別當一個類引用不支持串行化的間接對象或引用含有循環結構的時候。

 

適用場景:

原型模式是在內存二進制流的拷貝,比直接new一個對象性能好很多,特別是需要大量對象時,可以考慮使用原型模式。

類實例化需要消耗非常多的資源時或者實例化需要復雜的數據準備訪問權限時。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 元朗区| 柳河县| 长岛县| 视频| 韶关市| 汝州市| 洛扎县| 永嘉县| 那曲县| 绍兴市| 汪清县| 商都县| 晋中市| 青田县| 白沙| 安徽省| 内乡县| 准格尔旗| 乐东| 义马市| 磐石市| 平武县| 吴忠市| 山东省| 竹北市| 马龙县| 昆山市| 清新县| 木兰县| 张家口市| 奉化市| 永吉县| 镇安县| 大理市| 资中县| 泰来县| 榕江县| 靖安县| 舒兰市| 龙胜| 民和|