版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37080285/article/details/86512327
原型模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。
class Program
{
static void Main(string[] args)
{
ShapePrototype shape = new RealPrototype(1);
ShapePrototype real1 = shape.Clone() as RealPrototype;
shape.Id = 2;
Console.WriteLine("Clone1:\t" + real1.Id);
ShapePrototype real2 = shape.Clone() as RealPrototype;
Console.WriteLine("Clone2:\t" + real2.Id);
Console.ReadLine();
}
}
public abstract class ShapePrototype
{
public int Id { get; set; }
public ShapePrototype(int id)
{
Id = id;
}
public abstract ShapePrototype Clone();
}
public class RealPrototype : ShapePrototype
{
public RealPrototype(int id)
: base(id)
{ }
public override ShapePrototype Clone()
{
// 调用MemberwiseClone方法实现的是浅拷贝
return (ShapePrototype)this.MemberwiseClone();
}
}
显示结果
Clone1:1
Clone2:2
说明拷贝成功了,修改原型没有改变拷贝的对象。
浅拷贝是指副本对象中的引用类型的数据成员与源对象的数据成员指向相同的对象。而如果是深拷贝,则必须创建整个对象的结构,副本对象中的引用类型的数据成员与源对象的数据成员指向不同的对象。
浅拷贝是容易实现的,就是使用前面提到的MemberwiseClone方法。开发人员往往希望使用的类型能够实现深拷贝,但会发现这样的类型并不 多。这种情况在System.Collections命名空间中尤其常见,这里面的类在其Clone方法中实现的都是浅拷贝。这么做主要出于两个原因:
- 创建一个大对象的副本对性能影响较大。
- 通用的集合类型可能会包含各种各样的对象,在这种情况下实现深拷贝并不可行,因为集合中的对象并非都是可克隆的,另外还存在循环引用的情况,这会让深拷贝过程陷入死循环。
对于强类型的集合情况有所不同,因为它包含的元素是可控制的,此时深拷贝变得有用,同时也是可行的。例如System.Xml.XmlNode在其Clone方法中实现了深拷贝。
深拷贝:
class Program
{
static void Main(string[] args)
{
ShapePrototype shape = new RealPrototype(new List<int>() { 1 });
ShapePrototype real1 = shape.Clone() as RealPrototype;
shape.Id[0] = 2 ;
Console.WriteLine("Cloned1:\t" + real1.Id[0]);
ShapePrototype real2 = shape.Clone() as RealPrototype;
Console.WriteLine("Cloned2:\t" + real2.Id[0]);
Console.ReadLine();
}
}
public abstract class ShapePrototype
{
public List<int> Id = new List<int>();
public ShapePrototype()
{
}
public abstract ShapePrototype Clone();
}
public class RealPrototype : ShapePrototype
{
public RealPrototype(List<int> id)
: base()
{
foreach (int e in id)
{
Id.Add(e);
}
}
public override ShapePrototype Clone()
{
return new RealPrototype(Id);
// 调用MemberwiseClone方法实现的是浅拷贝
//return (ShapePrototype)this.MemberwiseClone();
}
}
显示结果
Clone1:1
Clone2:2
虽然结果还是这个,但实际上把Clone方法里注释的那句话改为:
public override ShapePrototype Clone()
{
//return new RealPrototype(Id);
// 调用MemberwiseClone方法实现的是浅拷贝
return (ShapePrototype)this.MemberwiseClone();
}
显示结果
Clone1:2
Clone2:2
标题.NET中原型模式的实现
在.NET中可以很容易地通过实现ICloneable接口(这个接口就是原型,提供克隆方法,相当于与上面代码中ShapePrototype抽象类)中Clone()方法来实现原型模式,如果我们想我们自定义的类具有克隆的功能,首先定义类继承与ICloneable接口并实现Clone方法。
改为本例就是这样:
class Program
{
static void Main(string[] args)
{
ShapePrototype shape = new ShapePrototype(new List<int>() { 1 });
ShapePrototype real1 = shape.Clone() as ShapePrototype;
shape.Id[0] = 2 ;
Console.WriteLine("Cloned1:\t" + real1.Id[0]);
ShapePrototype real2 = shape.Clone() as ShapePrototype;
Console.WriteLine("Cloned2:\t" + real2.Id[0]);
Console.ReadLine();
}
}
public class ShapePrototype : ICloneable
{
public List<int> Id = new List<int>();
public ShapePrototype(List<int> id)
{
foreach (int e in id)
{
Id.Add(e);
}
}
public object Clone()
{
return new ShapePrototype(Id);
}
}