C# 在原型设计模式中,浅复制与分配、深复制与使用新关键字创建新对象之间的区别
所以我在学习设计模式,今天我遇到了原型设计模式。我创建了原型界面,它包含2个方法(CloneShallow和CloneDeep)。我创建了一个平凡的类Employee,它实现了原型接口,有两个属性(Id和FullName)。代码非常简单C# 在原型设计模式中,浅复制与分配、深复制与使用新关键字创建新对象之间的区别,c#,design-patterns,C#,Design Patterns,所以我在学习设计模式,今天我遇到了原型设计模式。我创建了原型界面,它包含2个方法(CloneShallow和CloneDeep)。我创建了一个平凡的类Employee,它实现了原型接口,有两个属性(Id和FullName)。代码非常简单 public interface Prototype { public Prototype CloneShallow(); public Prototype CloneDeep(); } public class Employee : Pro
public interface Prototype
{
public Prototype CloneShallow();
public Prototype CloneDeep();
}
public class Employee : Prototype
{
public int Id { get; set; }
public string FullName { get; set; }
public Employee(int id,string fullName)
{
this.Id = id;
this.FullName = fullName;
}
public Prototype CloneShallow()
{
return this;
}
public Prototype CloneDeep()
{
return new Employee(Id, FullName);
}
public void printInfo()
{
Console.WriteLine($"Id: {Id}");
Console.WriteLine($"Full name: {FullName}");
}
}
大体上
class Program
{
static void Main(string[] args)
{
Employee original = new Employee(1, "First Employee");
Employee copyPrototype = (Employee)original.CloneShallow();
Employee copyAssigned = original;
Employee deepCopy = (Employee)original.CloneDeep();
Employee newDeepCopy = new Employee(original.Id, original.FullName);
}
}
我创建了名为original的对象。之后,我使用CloneShallow()方法执行了浅层复制,而我们的对象original和copyPrototype指向相同的地址位置。在那之后,我指定了对象copy指定了名为original(shallcopy aswel)的对象的addres
为了对原始对象进行深度复制,deepCopy对象使用CloneDeep()方法为其分配新的内存空间,newDeepCopy使用new关键字
我有点困惑。copyAssigned对象与CopyPrototype相同(两个对象都指向同一内存地址),而newDeepCopy对象与deepCopy对象相同(创建时,每个对象都具有唯一的内存位置,并具有各自复制的属性)。我肯定错过了什么,因为我看不到它的好处
任何人都可以给出这个模式的真实例子,或者至少解释一下它的用途吗?原型模式是一种创造性的设计模式。这是一种允许复制/克隆(创建)实例的模式 克隆,即浅复制意味着:创建一个对象的新实例,但重用/复制其所有字段/引用。原始实例的数据将复制到新实例。每个克隆引用都指向与其原始引用相同的内存位置(对于引用类型) 与深度克隆(即深度复制)相反:创建对象的新实例,但其所有字段/引用都用新实例初始化。原始实例的数据将替换为新实例。每个克隆的引用指向与其原始引用不同的内存位置 当内部引用/字段过于昂贵而无法为每个实例创建新引用/字段时,克隆/浅复制非常有用。相反,您可能希望创建现有实例(原型)的浅层副本,以重用内部引用的对象实例。
您可以缓存初始实例并通过克隆将其相乘。在这种情况下,您将只希望使用浅拷贝(克隆)实现原型模式 当您希望将原型用作工厂形式(抽象工厂也是一种创造性模式)以消除对(具体)类型的依赖时,深度克隆/深度复制非常有用。
当您有一个类
Employer
需要动态创建例如appoint
的实例时,您可以使用iappoint
的原型来创建它们。这样做的好处是,您可以创建实例,而无需将紧耦合引入实现类型Appointment
:使用具体类型,而不是newappointment()
,现在可以在抽象类型上调用IAppointment.DeepClone()
。在这种情况下,目标是避免与实现紧密耦合,您可以提供深度克隆,即原型的深度副本
您的示例实现了错误的克隆。
当前的
CloneShallow
实现返回相同的实例(自身):
您当前的CloneDeep
实际上执行CloneShallow
应该执行的操作:将数据复制到新实例:
public Prototype CloneDeep()
{
// Creates a new instance that references the same data (wrong)
return new Employee { Appointment = this.Appointment };
}
Employee prototype = new Employee();
Employee clone = prototype.CloneDeep() as Employee;
// Returns 'false' => the original instance was successfully copied to a new instance, ...
bool isTheSameInstance = object.ReferenceEquals(prototype, clone);
// ...but the data is still the same => shallow copy or clone
isTheSameInstance = object.ReferenceEquals(propotype.Appointment, clone.Appointment); // true
要让类创建自身的浅拷贝/克隆,建议使用(该链接还再次解释了克隆/深度克隆之间的区别)
原型模式的正确和改进实现可能如下所示:
public interface IPrototype<T>
{
// Shallow copy.
// Use this if you want to use the prototype to create new instances while saving memory or resources
// by reusing/copying all internal references
public T Clone();
// Use this to create a new instance where all internal references are also new instances.
public T DeepClone();
}
public class Employee : IPrototype<Employee>
{
public IAppointment Appointment { get; set; }
public string FullName { get; set; }
public Employee()
{
this.Appointment = new Appointment();
this.FullName = "Tony Montana";
}
public Employee Clone()
{
// Create a new instance which is a shallow copy of 'this'
return object.MemberwiseClone() as Employee;
}
public Employee DeepClone()
{
// Create a new instance using Clone().
// This way we only need to replace all reference types as value types linke 'int' are new references by language design
var newEmployee = Clone();
// Create new instances of the internal references too
newEmployee.Appointment = new Appointment();
newEmployee.FullName = String.Copy(this.FullName);
return newEmployee;
}
}
原型模式是一种创造性的设计模式。这是一种允许复制/克隆(创建)实例的模式 克隆,即浅复制意味着:创建一个对象的新实例,但重用/复制其所有字段/引用。原始实例的数据将复制到新实例。每个克隆引用都指向与其原始引用相同的内存位置(对于引用类型) 与深度克隆(即深度复制)相反:创建对象的新实例,但其所有字段/引用都用新实例初始化。原始实例的数据将替换为新实例。每个克隆的引用指向与其原始引用不同的内存位置 当内部引用/字段过于昂贵而无法为每个实例创建新引用/字段时,克隆/浅复制非常有用。相反,您可能希望创建现有实例(原型)的浅层副本,以重用内部引用的对象实例。
您可以缓存初始实例并通过克隆将其相乘。在这种情况下,您将只希望使用浅拷贝(克隆)实现原型模式 当您希望将原型用作工厂形式(抽象工厂也是一种创造性模式)以消除对(具体)类型的依赖时,深度克隆/深度复制非常有用。
当您有一个类
Employer
需要动态创建例如appoint
的实例时,您可以使用iappoint
的原型来创建它们。这样做的好处是,您可以创建实例,而无需将紧耦合引入实现类型Appointment
:使用具体类型,而不是newappointment()
,现在可以在抽象类型上调用IAppointment.DeepClone()
。在这种情况下,目标是避免与实现紧密耦合,您可以提供深度克隆,即原型的深度副本
您的示例实现了错误的克隆。
当前
CloneShall
public interface IPrototype<T>
{
// Shallow copy.
// Use this if you want to use the prototype to create new instances while saving memory or resources
// by reusing/copying all internal references
public T Clone();
// Use this to create a new instance where all internal references are also new instances.
public T DeepClone();
}
public class Employee : IPrototype<Employee>
{
public IAppointment Appointment { get; set; }
public string FullName { get; set; }
public Employee()
{
this.Appointment = new Appointment();
this.FullName = "Tony Montana";
}
public Employee Clone()
{
// Create a new instance which is a shallow copy of 'this'
return object.MemberwiseClone() as Employee;
}
public Employee DeepClone()
{
// Create a new instance using Clone().
// This way we only need to replace all reference types as value types linke 'int' are new references by language design
var newEmployee = Clone();
// Create new instances of the internal references too
newEmployee.Appointment = new Appointment();
newEmployee.FullName = String.Copy(this.FullName);
return newEmployee;
}
}
Employee prototype = new Employee();
Employee deepClone = prototype.DeepClone();
// Returns 'false' => the original instance was successfully copied to a new instance, ...
bool isTheSameInstance = object.ReferenceEquals(prototype, deepClone);
// ...and also the data is not the same => deep copy or deep clone
isTheSameInstance = object.ReferenceEquals(prototype.Appointment, deepClone.Appointment); // false