【设计模式】C#设计模式:原型模式

【设计模式】面向对象设计七大原则
【设计模式】设计模式概念和分类
【设计模式】C#设计模式:单例模式
【设计模式】C#设计模式:工厂方法模式
【设计模式】C#设计模式:抽象工厂模式
【设计模式】C#设计模式:建造者模式
【设计模式】C#设计模式:原型模式

原型模式定义

原型模式(Prototype Pattern):是一种对象创建型模式,用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。原型模式允许一个对象再创建另外一个可定制的对象,无须知道任何创建的细节。原型模式的基本工作原理是通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝原型自己来实现创建过程。通过复制一个已经存在的实例来创建一个新的实例。被复制的实例被称为原型,这个原型是可定制的。

原型模式结构

抽象原型(Prototype):这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体原型类所需的接口。在 C#中,抽象原型角色通常实现了 ICloneable 接口。
具体原型(Concrete Prototype):被复制的对象。此角色需要实现抽象的原型角色所要求的接口。
客户(Client):客户端类向原型管理器提出创建对象的请求。
原型管理器(Prototype Manager):创建具体原型类的对象,并记录每一个被创建的对象。

原型模式分析

在原型模式结构中定义了一个抽象原型类,实现.NET的System命名空间为我们提供了一个ICloneable接口,它包含了一个方法Clone(),提供该类型的对象的副本,来实现对象的拷贝。

通常情况下,一个类包含一些成员对象,在使用原型模式克隆对象时,根据其成员对象是否也拷贝,原型模式可以分为两种形式:深拷贝浅拷贝

ICloneable接口

该接口使你能够创建现有对象的副本的自定义的实现。该接口只提供了,一个Clone方法,实现对象的浅拷贝。有浅拷贝,那么就有相对应的深拷贝。但该接口并没有对我们提供,需要我们自己实现。

浅拷贝

浅拷贝(Shallow Clone):当原型对象被复制时,只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有复制。将原来对象中的所有字段逐个复制到一个新对象,如果字段是值类型,则简单地复制一个副本到新对象,改变新对象的值类型字段不会影响原对象;如果字段是引用类型,则复制的是引用,改变目标对象中引用类型字段的值将会影响原对象。

在C#中调用 MemberwiseClone() 方法即为浅复制。如果字段是值类型的,则对字段执行逐位复制,如果字段是引用类型的,则复制对象的引用,而不复制对象。

C#中浅拷贝方法介绍:

public class ShallowClone : ICloneable
{
	/// <summary>
	/// 浅克隆
	/// </summary>
	/// <returns></returns>
	public object Clone()
	{
		return this.MemberwiseClone();
	}
}

深拷贝

深拷贝(Deep Clone):除了对象本身被复制外,对象所包含的所有成员变量也将被复制。与浅复制不同之处在于对引用类型的处理,深复制将新对象中引用类型字段指向复制过的新对象,改变新对象中引用的任何对象,不会影响到原来的对象中对应字段的内容。

C#中深拷贝方法介绍:
利用反射实现

public static T DeepCopy<T>(T obj)
{
	//如果是字符串或值类型则直接返回
	if (obj is string || obj.GetType().IsValueType) return obj;
	
	object retval = Activator.CreateInstance(obj.GetType());
	FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
	foreach (FieldInfo field in fields)
	{
		try { field.SetValue(retval, DeepCopy(field.GetValue(obj))); }
		catch { }
	}
	return (T)retval;
}

利用xml序列化和反序列化实现

public static T DeepCopy<T>(T obj)
{
	object retval;
	using (MemoryStream ms = new MemoryStream())
	{
		XmlSerializer xml = new XmlSerializer(typeof(T));
		xml.Serialize(ms, obj);
		ms.Seek(0, SeekOrigin.Begin);
		retval = xml.Deserialize(ms);
		ms.Close();
	}
	return (T)retval;
}

利用二进制序列化和反序列化实现

public static T DeepCopy<T>(T obj)
{
	object retval;
	using (MemoryStream ms = new MemoryStream())
	{
		BinaryFormatter bf = new BinaryFormatter();
		//序列化成流
		bf.Serialize(ms, obj);
		ms.Seek(0, SeekOrigin.Begin);
		//反序列化成对象
		retval = bf.Deserialize(ms);
		ms.Close();
	}
	return (T)retval;
}

原型模式实例

在这里插入代码片

原型模式优点

隐藏了对象的创建细节,对有些初始化需要占用很多资源的类来说,对性能也有很大提高。
在需要新对象时,可以使用Clone来快速创建创建一个,而不用使用new来构建。

原型模式缺点

每一个类都需要一个Clone方法,而且必须通盘考虑。对于深拷贝来说,每个关联到的类型都不许实现IClonable接口,并且每增加或修改一个字段是都需要更新Clone方法。

原型模式使用场景

(1)类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等
(2)通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式
(3)一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
(4)在实际项目中,原型模式很少单独出现,一般是和工厂模式一起出现,通过Clone方法创建一个对象,然后由工厂方法提供给调用者。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JIQIU.YANG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值