概述
原型模式,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式实质就是从一个对象再创建另外一个可定制的对象。而且不需要知道任何创建的细节。
原型模式的核心在克隆。
理论
为什么要使用克隆?
因为对象是通过构造函数来创建的,如果我们要创建A/B/C三个对象,不采用克隆的话需将对象实例化三次,故构造函数中将存在大量的业务逻辑,那么在对象的创建过程中就会消耗不少资源(如时间)。
如果我们用克隆呢?既隐藏了对象创建的细节,又对性能大大的提高。
什么时候使用克隆?
一般在初始化的信息不发生变动的情况下,不用重新初始化对象,而是动态的获得对象运行时的状态,克隆是最好的方法。
怎么应用克隆?
.net 在system 命名空间中提供了ICloneable 接口(声明克隆),其中唯一的一个方法Clone(),实现这个接口就可以完成原型模式(克隆)。
浅复制
如果字段是值类型的,则对字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其副本引用同一对象。
Ps:如果类中有对象引用,那么对象数据是不会被克隆的。
深复制
深复制吧引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。
基本类型 | 引用类型属性 | 引用类型备注 |
---|---|---|
浅复制 | 复制引用,执行原引用的地址 | 如果修改引用的属性,会影响另外一个对象 |
深复制 | 复制引用和引用的内容,并创建新的实例,指向新的地址 | 创建一个新的对象,把原对象的内容复制到新对象中 |
例:原始对象P1,通过浅复制得到对象P2,通过深复制得到P3
原始对象P1中的值类型属性有:Age 和 Name ,引用类型对象有:IdInfo
根据上述浅复制的概念可知:P2中的Age 和 Name 相对于 P1是全新的,但P2中的 IdInfo 和 P1中的 IdInfo 是同一个对象,二者同在一个内存地址!
根据上述深复制的概念可知:P3中的Age 和 Name 相对于 P1是全新的,但P3中的 IdInfo 和 P1中的 IdInfo 不是同一个对象,也就是说 P3中的IdInfo是一个全新的对象,开辟了自己的内存地址!
模式中的角色
◊ Prototype:原型类,声明一个Clone自身的接口;
◊ ConcretePrototype:具体原型类,实现一个Clone自身的操作。
在原型模式中,Prototype通常提供一个包含Clone方法的接口,ConcretePrototype使用Clone方法完成对象的创建。
原型模式优点
- 原型模式向客户隐藏了创建新实例的复杂性
- 原型模式允许动态增加或较少产品类。
- 原型模式简化了实例的创建结构,工厂方法模式需要有一个与产品类等级结构相同的等级结构,而原型模式不需要这样。
- 产品类不需要事先确定产品的等级结构,因为原型模式适用于任何的等级结构
原型模式缺点
- 每个类必须配备一个克隆方法
- 配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。
代码
class Program
{
static void Main(string[] args)
{
Resume a = new Resume("大鸟");
a.SetPersonalInfo("男","29");
a.SetWorkExperience("1998-2000","xx公司");
Resume b = (Resume) a.Clone();
b.SetWorkExperience("1998-2006","YY企业");
Resume c = (Resume) a.Clone();
c.SetPersonalInfo("男","24");
a.Display();
b.Display();
c.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 SetPersonalInfo(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("工作经历:{0}{1}",timeArea,company);
}
public Object Clone()
{
return (Object) this.MemberwiseClone();
}
}
小结
学历彰显你的过去,能力代表你的现在,学习决定你的将来!