原型模式(Prototype)用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节 。

原型类 Prototype:

abstract class Prototype

{

private string id;

public Prototype(string id)

{

this.id = id;

}

public string Id

{

get { return id; }

}

//抽象类关键有这样一个Clone方法

public abstract Prototype Clone();

}

 ConcretePrototypel类,具体原型

class ConcretePrototypel : Prototype

{

public ConcretePrototypel(string id) : base(id) { }

public override Prototype Clone()

{

//创建一个新对象,然后将当前对象非静态字段复制到该新对象

//如果字段是值类型,则逐位复制字段,引用类型只复制引用地址

return (Prototype)this.MemberwiseClone();

}

}

客户端:

class Main : MonoBehaviour

{

private void Start()

{

ConcretePrototypel pl = new ConcretePrototypel("I");

ConcretePrototypel cl = (ConcretePrototypel)pl.Clone();

Debug.Log("clone" + cl.Id);

}

}

由于克隆实在太常用,.Net在System命名空间提供了IClone接口,唯一的Clone()方法,只要实现这个接口就可以完成原型模式了。

 简历类:

class Resume : ICloneable

{

private string name;

private string sex;

private string age;

private string timearea;

private string company;

public Resume(string name)

{

this.name = name;

}

//设置个人信息

public void SetPersonalInfo(string sex,string age)

{

this.sex = sex;

this.age = age;

}

//设置工作经历

public void SetWorkExperrience(string timeArea,string company)

{

this.timearea = timeArea;

this.company = company;

}

//显示

public void Display()

{

//实现接口方法,克隆对象

Debug.Log(name + " " + sex + " " + age);

Debug.Log(timearea + " " + company);

}

public object Clone()

{

return (object)this.MemberwiseClone();

}

}

客户端:

class Main : MonoBehaviour

{

private void Start()

{

Resume a = new Resume("DJ");

a.SetPersonalInfo("男", "22");

a.SetWorkExperrience("1995-2022", "DJDJ");

//调用克隆方法就可以实现新简历,并且可以修改新简历细节

Resume b = (Resume)a.Clone();

b.SetPersonalInfo("nv", "20");

Resume c = (Resume)a.Clone();

c.SetWorkExperrience("1999-2222", "JJJJ");

a.Display();

b.Display();

c.Display();

}

}

输出结果:

        现实设计当中,一般会再有一个“工作经历”类,当中有“时间区间”和“公司名称”等属性,“简历”类直接调用。

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();//简历实例化同时实例化工作经历

}

public void SetPersonalInfo(string sex,string age)

{

this.sex = sex;

this.age = age;

}

public void SetWorkExperrience(string workDate,string company)

{

work.WorkDate = workDate;//调用方法,给对象赋值

work.Company = company;

}

public void Display()

{

Debug.Log(name + " " + sex + " " + age);

Debug.Log(work.WorkDate + " " + work.Company);//显示工作经历属性值

}

public object Clone()

{

return (object)this.MemberwiseClone();

}

}

class WorkExperience

{

private string workDate;

public string WorkDate

{

get { return workDate; }

set { workDate = value; }

}

private string company;

public string Company

{

get { return company; }

set { company = value; }

}

}

使用之前的客户端逻辑,运行后结果:

        对于引用类型,克隆后没有实现真正的克隆,而是只克隆了引用地址,这叫做“浅复制”,被复制对象的所有变量都含有与原来的对象相同的值;而所有的对其他对象的引用都仍然指向原来的对象。

深复制把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。

深复制流程:

首先修改WorkExperience类,增加克隆方法

class WorkExperience

{

private string workDate;

public string WorkDate

{

get { return workDate; }

set { workDate = value; }

}

private string company;

public string Company

{

get { return company; }

set { company = value; }

}

public object Clone()

{

//工作经历类也实现克隆方法

return (object)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();

}

//提供Clone方法调用的私有构造函数,以便克隆工作经历数据

public Resume(WorkExperience work)

{

this.work = (WorkExperience)work.Clone();

}

public void SetPersonalInfo(string sex,string age)

{

this.sex = sex;

this.age = age;

}

public void SetWorkExperrience(string workDate,string company)

{

work.WorkDate = workDate;

work.Company = company;

}

public void Display()

{

Debug.Log(name + " " + sex + " " + age);

Debug.Log(work.WorkDate + " " + work.Company);

}

//调用私有构造方法,让工作经历克隆,然后再给新对象其他字段赋值

//最终返回一个深复制的简历对象

public object Clone()

{

Resume obj = new Resume(this.work);

obj.name = this.name;

obj.sex = this.sex;

obj.age = this.age;

return obj;

}

}

还是使用之前的客户端逻辑,结果如下。 

文章链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。