原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象


原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道创建的细节

UML图:

undefined

实现:

//原型类
abstract class Prototype
{
    private string id;

    public Prototype(string id)
    {
        this.id = id;
    }

    public string ID {
        get { return id; }
    }

    public abstract Prototype Clone();
}

//具体原型类
class ConcretePrototype1 : Prototype
{
    //提供与父类构造函数参数相同的构造函数
    public ConcretePrototype1(string id) : base(id)
    {

    }

    public override Prototype Clone()
    {
        //创建当前对象的浅表副本。方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型,则对该字段执行逐位复制。如果字段是引用类型,则复制引用但不复制引用的对象;因此原始对象及其副本应用同一对象[MSDN]
        return (Prototype)this.MemberwiseClone();
    }
}

//客户端
	   static void Main(string[] args) {
            ConcretePrototype1 p1 = new ConcretePrototype1("Ayosi");
            ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone();

            Console.WriteLine("Clone: {0}", c1.ID);

            Console.Read();
        }

.Net在System命名空间中提供了ICloneable接口,这个接口中维一的方法是Clone(),实现这个接口即可完成原型模式。

深度复制:

对于深拷贝和浅拷贝的解析:C#进阶系列

UML:

undefined

实现

class WorkExperience : ICloneable
{
    public string WorkDate {
        get;
        set;
    }

    public string Company {
        get;
        set;
    }

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

class Resume : ICloneable
{
    private string name;
    private string sex;
    private string age;
    private WorkExperience work;

    public Resume(string name)
    {
        this.name = name;
        work = new WorkExperience();
    }

    private Resume(WorkExperience work)
    {
        //提供Clone方法调用的私有构造函数,以便克隆“工作经历”的数据
        this.work = (WorkExperience)work.Clone();
    }

    //设置个人信息
    public void SetPersonalInfo(string sex,string age)
    {
        this.sex = sex;
        this.age = age;
    }
    //设置工作经历
    public void SetWorkExperience(string workDate,string company)
    {
        work.WorkDate = workDate;
        work.Company = company;
    }

    public object Clone()
    {
        //调用私有的构造方法,让“工作经历”克隆完成,然后再给这个“简历”对象的相关字段赋值,最终返回一个深复制的简历对象
        Resume obj = new Resume(this.work);

        obj.name = this.name;
        obj.sex = this.sex;
        obj.age = this.age;

        return obj;
    }
}

浅表复制是只能拷贝当前层中的值类型数据,对于更深层的数据需要在更深层出实现ICloneable接口

参考:
[1] 大话设计模式,程杰