设计模式

目的:当需要多次实例化同一个对象时,可以通过 Clone 已有对象的方式避免多次实例化,从而节约性能。

1. 雏形

/// <summary>
/// 抽象原型类
/// </summary>
public abstract class Prototype
{
    public abstract Prototype Clone();
}


public class Companey
{
    public string Name { get; set; }
    public string Place { get; set; }
}

/// <summary>
/// 具体原型类
/// </summary>
public class Resume : Prototype
{
    public string Name { get; set; }
    
    public Companey Com { get; set; }

    public object Clone()
    {
        return (object)this.MemberwiseClone();
    }
    public void Show()
    {
        Console.WriteLine( string.Format("{0} 的公司在{1}", name, Com.Name + Com.Place));
    }
}

Resume a = new Resume() { Name = "Mao", Com = new Companey() { Name = "Gxx", Place = "2819" } };
Resume b = (Resume)a.Clone();
Resume c = (Resume)a.Clone();
a.Show();
b.Show();
c.Show();

a.Name = "a";
b.Name = "b";
a.Show();
b.Show();
c.Show();

b、c 克隆自a,但是修改 a 的 Name 对 b、c 并无影响,同理修改 b 的 Name 也是,输出结果如下:

Mao 公司在Gxx2819
Mao 公司在Gxx2819
Mao 公司在Gxx2819

a 公司在Gxx2819
b 公司在Gxx2819
Mao 公司在Gxx2819

2. C# 现成的 ICloneable

C# 有现成的 ICloneable 接口,与我们写的 Prototype 类实现的功能一样。

public class Resume : ICloneable { }

3. 浅复制和深复制

上面 a 的 Name 属性的类型是 string,值类型,因此修改 a 的 Name 的值对 b、c 没有影响,但是修改引用类型的 Com 属性,将会有影响,如下:

Resume a = new Resume() { Name = "Mao", Com = new Companey() { Name = "Gxx", Place = "2819" } };
Resume b = (Resume)a.Clone();
Resume c = (Resume)a.Clone();
a.Show();
b.Show();
c.Show();

a.Name = "a";
a.Com.Place = "2866";
b.Name = "b";
b.Com.Place = "2828";
a.Show();
b.Show();
c.Show();

输出:

Mao 公司在Gxx2819
Mao 公司在Gxx2819
Mao 公司在Gxx2819

a 公司在Gxx2828
b 公司在Gxx2828
Mao 公司在Gxx2828

这就叫浅复制,将 a 对象的所有值类型的属性复制一遍,但是引用类型的属性依旧使用同一个,并没有复制.

4. 实现深复制

public class Companey : ICloneable
{
    public string Name { get; set; }

    public string Place { get; set; }

    public object Clone()
    {
        return (object)this.MemberwiseClone();
    }
}

public class Resume : ICloneable
{
    ...
    
    public Resume() { }

    public Resume(Companey com)
    {
        this.Com = (Companey)com.Clone();
    }

    public object Clone()
    {
        Resume obj = new Resume(this.Com);
        obj.Name = this.Name;
        obj.Age = this.Age;
        obj.Sex = this.Sex;
        return obj;
    }
}

输出:

Mao 公司在Gxx2819
Mao 公司在Gxx2819
Mao 公司在Gxx2819

a 公司在Gxx2866
b 公司在Gxx2828
Mao 公司在Gxx2819
原文地址:https://www.cnblogs.com/MichaelLoveSna/p/14141690.html