参考:head first 设计模式
应用场景
对象的克隆,复制。有一个对象了,通过对它的复制来创建一个相同或类似的新对象。
如细胞分裂,1分2,2分4,再无限分。
结构
1.通过ICloneable接口来实现,或者搞一个抽象类。.net中用前者好些。
2.抽象类的方式如下:
原型:Prototype
具体原型类:ConcretePrototype 可以复制的对象继承自Prototype
客户端调用:PrototypeClient来调用上面的Clone来创建对象
图例
特点
优点:
向客户隐藏创建的复杂性,可以动态的增加或减少产品类。适用于任何结构,无须先确定产品的等级结构。
缺点:
每个类必须有克隆的方法,有循环结构的对象的话会麻烦。
系统自带
ICloneable
代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DesignPattern
{
public class PrototypeClient
{
public static void main()
{
//方式1
Prototype ptype = new ConcretePrototype("abstracttype", "abstract");
Prototype pt1 = ptype.Clone();
Console.WriteLine(pt1.Name);
Prototype pt2 = ptype.Clone();
Console.WriteLine(pt2.Name);
Console.WriteLine(pt1.Equals(pt2));//false hashcode不同 referernce不同 内存地址不同
//方式2
ConcretePrototypeInterface pti1 = new ConcretePrototypeInterface();
pti1.Name = "prototype interface";
pti1.Type ="interface";
ConcretePrototypeInterface pti2 = pti1.Clone() as ConcretePrototypeInterface;
Console.WriteLine(pti1.Equals(pti2));//true 如果没有重写Equals仍为false
Console.WriteLine(ReferenceEquals(pti1, pti2));//false
}
}
/// <summary>
/// 抽象原型
/// </summary>
public abstract class Prototype
{
public string Name { get; set; }
public string Type { get; set; }
public Prototype(string id, string type)
{
this.Name = id;
this.Type = type;
}
//克隆
public abstract Prototype Clone();
}
/// <summary>
/// 具体原型对象
/// </summary>
public class ConcretePrototype : Prototype
{
public ConcretePrototype(string name, string type) : base(name, type)
{
}
//浅拷贝,只拷贝值,不拷贝引用; 深拷贝需要拷贝引用
public override Prototype Clone()
{
return (Prototype)this.MemberwiseClone();
}
}
public class ConcretePrototypeInterface : ICloneable,IEquatable<ConcretePrototypeInterface>
{
public string Name { get; set; }
public string Type { get; set; }
public object Clone()
{
return new ConcretePrototypeInterface() { Name = this.Name, Type = this.Type };
}
public bool Equals(ConcretePrototypeInterface other)
{
return this.Name.Equals(other.Name) && this.Type.Equals(other.Type);
}
}
}