设计模式 - 7) 原型模式
目的:当需要多次实例化同一个对象时,可以通过 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