設計模式(C#)——原型模式
推薦閱讀:
在軟體開發過程中,我們習慣使用new來建立物件。但是當我們建立一個例項的過程很昂貴或者很複雜,並且需要建立多個這樣的類的例項時。如果仍然用new操作符去建立這樣的類的例項,會導致記憶體中多分配一個一樣的類例項物件,增加建立類的複雜度和消耗更多的記憶體空間。
如果採用簡單工廠模式來建立這樣的系統。隨著產品類增加,子類數量不斷增加,會增加額外系統複雜程度,為此我們不得不引入原型模式了。
原型模式(Prototype Pattern)
原型模式:建立重複的物件,同時又能保證效能。這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式。
那麼,我們如何用原型模型解決上面的問題呢?
在原型模型中,因為每個類例項都是相同的,當我們需要多個相同的類例項時我們可以考慮只建立一個類例項物件,如果後面需要更多這樣的例項,可以通過對原來物件拷貝一份來完成建立,這樣在記憶體中不需要建立多個相同的類例項,從而減少記憶體的消耗和達到類例項的複用。
原型模式要素:
①抽象原型:宣告一個克隆自身的介面;
②具體原型:該類繼承了原型類,用來實現一個克隆自身的操作。
克隆操作分為:
淺克隆(Shallow Clone):當原型物件被複制時,只複製它本身和其中包含的值型別的成員變數,而引用型別的成員變數並沒有複製,它們只是指向同一個引用。
深克隆(Deep Clone):除了物件本身被複制外,物件所包含的所有成員變數也將被複制,它們擁有不同的副本。
下面舉個孫悟空複製猴子猴孫的例子來幫助大家理解原型模式:
名稱空間原型模式,包含孫悟空基類MonkeyKing,孫悟空就是原型模式中的原型物件;實現類建立猴子猴孫CreateMonkey,另外包含CloneBase泛型基類。
1建立孫悟空基類MonkeyKing
abstract class MonkeyKing
{
public abstract Prototype Clone();
}
2.建立悟空子類CreateMonkey
class CreateMonkey: MonkeyKing
{
private string monkey; //成員變數
public string monkey
{
get { return monkey; }
set { monkey= value; }
}
//克隆方法
public override MonkeyKing Clone()
{
CreateMonkey monkeyKing= new CreateMonkey();
monkeyKing.monkey= monkey;
return monkeyKing;
}
}
3.使用原型模型
namespace 抽象工廠模式
{
class Program
{
static void Main(string[] args)
{
CreateMonkey createMonkey = new CreateMonkey();
CreateMonkey copy = (CreateMonkey)createMonkey.Clone();
Console.ReadLine();
}
}
}
上面我們簡單使用原型模式來實現孫悟空克隆猴子猴孫。由於前面我們講到從具體原型的克隆方法分為淺克隆和深克隆,下面我將繼續帶領大家使用C#提供的MemberwiseClone()方法和ICloneable介面來實現淺克隆和深克隆。
一.淺克隆
1.建立抽象原型WorkExperience
class WorkExperience : ICloneable
{
private string workDate;
public string WorkDate
{
get { return workDate; }
set { workDate = value; }
}
private string company;
public string Company
{
get { return company; }
set { company = value; }
}
public Object Clone()
{
return (object)this.MemberwiseClone();
}
}
2.建立具體原型
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 SetPersonalInfo(string sex, string age)
{
this.sex = sex;
this.age = age;
}
public void SetWorkExperience(string workDate, string company)
{
work.WorkDate = workDate;
work.Company = company;
}
public void Display()
{
Console.WriteLine("{0},{1},{2}",name,sex,age);
Console.WriteLine("工作經歷 {0},{1}",work.WorkDate,work.Company);
}
public Object Clone()
{
return (Object)this.MemberwiseClone();
}
}
3.使用原型
class Program
{
static void Main(string[] args)
{
Resume a = new Resume("馬雲");
a.SetPersonalInfo("男", "40");
a.SetWorkExperience("2010--2018", "X公司");
Resume b = (Resume)a.Clone();
b.SetWorkExperience("2000--2010", "XX公司");
Resume c = (Resume)a.Clone();
c.SetPersonalInfo("男", "24");
c.SetWorkExperience("1993--2000", "XXX公司");
a.Display();//xxx公司
b.Display();//xxx公司
c.Display();//xxx公司
Console.ReadKey();
}
}
二.深克隆
1.建立抽象原型WorkExperience
class WorkExperience : ICloneable
{
private string workDate;
public string WorkDate
{
get { return workDate; }
set { workDate = value; }
}
private string company;
public string Company
{
get { return company; }
set { company = value; }
}
public Object Clone()
{
return (object)this.MemberwiseClone();
}
}
2.建立具體原型
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();
}
public void SetPersonalInfo(string sex, string age)
{
this.sex = sex;
this.age = age;
}
public void SetWorkExperience(string workDate, string company)
{
work.WorkDate = workDate;
work.Company = company;
}
public void Display()
{
Console.WriteLine("{0},{1},{2}",name,sex,age);
Console.WriteLine("工作經歷 {0},{1}",work.WorkDate,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;
}
}
3.使用原型
class Program
{
static void Main(string[] args)
{
Resume a = new Resume("靖凡");
a.SetPersonalInfo("男", "29");
a.SetWorkExperience("2010--2018", "X公司");
Resume b = (Resume)a.Clone();
b.SetWorkExperience("2000--2010", "XX公司");
Resume c = (Resume)a.Clone();
c.SetPersonalInfo("男", "24");
c.SetWorkExperience("1993--2000", "XXX公司");
a.Display();//x公司
b.Display();//xx公司
c.Display();//xxx公司
Console.ReadKey();
}
}
通過上面三個例子,如果你對原型模式有了更好的理解,麻煩文末點個贊,如果你有什麼疑惑,也歡迎評論區留言!!!