原型模式
- 设计模式
- 2024-06-19
- 628热度
- 0评论
一、概述
原型模式是一种特殊的创建型模式(对象创建型模式),它通过复制一个已有对象来获取更多相同或者相似的对象。原型模式可以提高相同类型对象的创建效率,简化创建过程。其中原型模式又分为浅拷贝和深拷贝。浅拷贝是指复制引用但不复制引用的对象,而深拷贝复制的引用和引用对象。
定义:使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象。
二、模式结构
-
Prototype(抽象原型类):它声明了克隆方法的接口,是所有具体原型类的公共父类,它可以是抽象类也可以是接口,甚至还可以是具体实现类。
-
ConcretePrototype(具体原型类):它实现抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。
-
Client类:让一个原型对象克隆自身从而创建一个新的对象。
三、具体实现
以简历为例,复制多份简历,使用原型模式来实现,由于C#中提供了ICloneable接口(抽象原型类),所有具体原型类实现IClonable接口。
3.1 浅拷贝
浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象, 某个对象修改,所有的对象都会随之一起修改。
- Resume(具体原型类):简历类
public 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 class Resume : ICloneable
{
private string _name;
private string _sex;
private string _age;
private WorkExperience workExperience;
public Resume(string name)
{
_name = name;
workExperience = new WorkExperience();
}
// 设置个人信息
public void SetPersonalInfo(string sex, string age)
{
_sex = sex;
_age = age;
}
// 设置工作经历
public void SetWorkExperience(string workData, string company)
{
workExperience.WorkDate = workData;
workExperience.Company = company;
}
// 显示
public void Display()
{
Console.WriteLine("{0} {1} {2}", _name, _sex, _age);
Console.WriteLine("工作经历: {0} {1}", workExperience.WorkDate, workExperience.Company);
}
public object Clone()
{
return (Object)MemberwiseClone();
}
}
-
Client类
Resume resume = new Resume("lwy"); resume.SetPersonalInfo("男", "23"); resume.SetWorkExperience("2023-2024", "xx公司"); Resume resume1 = (Resume)resume.Clone(); resume1.SetWorkExperience("2022-2023", "yy企业"); Resume resume2 = (Resume)resume.Clone(); resume2.SetPersonalInfo("男", "24"); resume.Display(); resume1.Display(); resume2.Display(); /* lwy 男 23 工作经历: 2022-2023 yy企业 lwy 男 23 工作经历: 2022-2023 yy企业 lwy 男 24 工作经历: 2022-2023 yy企业 */
string虽然是一种引用类型,但它属于拥有值类型特点的特殊应用类型, MemberwiseClone()方法是这样,如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。
3.2 深拷贝
深拷贝:深复制把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象,每个对象都独立存在。
- Resume(具体原型类):简历类
public class WorkExperience : ICloneable
{
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) this.MemberwiseClone();
}
}
public class Resume : ICloneable
{
private string _name;
private string _sex;
private string _age;
private WorkExperience workExperience;
public Resume(string name)
{
_name = name;
workExperience = new WorkExperience();
}
// 设置个人信息
public void SetPersonalInfo(string sex, string age)
{
_sex = sex;
_age = age;
}
// 设置工作经历
public void SetWorkExperience(string workData, string company)
{
workExperience.WorkDate = workData;
workExperience.Company = company;
}
// 显示
public void Display()
{
Console.WriteLine("{0} {1} {2}", _name, _sex, _age);
Console.WriteLine("工作经历: {0} {1}", workExperience.WorkDate, workExperience.Company);
}
public Object Clone()
{
Resume obj = new Resume(_name);
obj.workExperience = (WorkExperience)workExperience.Clone();
obj._sex = _sex;
obj._age = _age;
return obj;
}
}
-
Client类
Resume resume = new Resume("lwy"); resume.SetPersonalInfo("男", "23"); resume.SetWorkExperience("2023-2024", "xx公司"); Resume resume1 = (Resume)resume.Clone(); resume1.SetWorkExperience("2022-2023", "yy企业"); Resume resume2 = (Resume)resume.Clone(); resume2.SetPersonalInfo("男", "24"); resume.Display(); resume1.Display(); resume2.Display(); /* lwy 男 23 工作经历: 2023-2024 xx公司 lwy 男 23 工作经历: 2022-2023 yy企业 lwy 男 24 工作经历: 2023-2024 xx公司 */
四、优缺点
- 优点:
- 性能高:使用原型模式复用现有对象,比使用构造函数重新创建对象性能更高(直接在内存中拷贝,构造函数是不会执行的),适用于类实例对象开销较大的情况。
- 流程简单:原型模式可以简化创建过程,直接修改现有对象实例的值,达到复用的目的。
- 缺点:
- 实现复杂:需要覆盖clone方法,且需注意深拷贝和浅拷贝的风险,实现深拷贝需要将每一层的对象的类都支持深拷贝。
- 不符合开闭原则:因为每一个类配备一个克隆的方法,且该克隆方法位于类内部,当对已有的类进行修改时需要修改源代码。
五、适用环境
- 当需要在运行是动态地创建新对象,且不必知道它们确切类型时,可以采用原型模式。
- 当类初始化时消耗过多资源,或者构造函数复杂,或者需要避免创建新对象时所需的构造函数调用开销,都可以考虑使用原型模式。