Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在原型设计模式中,浅复制与分配、深复制与使用新关键字创建新对象之间的区别_C#_Design Patterns - Fatal编程技术网

C# 在原型设计模式中,浅复制与分配、深复制与使用新关键字创建新对象之间的区别

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

所以我在学习设计模式,今天我遇到了原型设计模式。我创建了原型界面,它包含2个方法(CloneShallow和CloneDeep)。我创建了一个平凡的类Employee,它实现了原型接口,有两个属性(Id和FullName)。代码非常简单

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