设计模式(C#)——04原型模式
推荐阅读:
在软件开发过程中,我们习惯使用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();
}
}
通过上面三个例子,如果你对原型模式有了更好的理解,麻烦文末点个赞,如果你有什么疑惑,也欢迎评论区留言!!!