原型模式
理论
原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节。
实例
要求有一个简历类,必须要有姓名,可以设置性别和年龄,可以设置工作经历。最终需要写三份简历。
初步实现
#include <iostream>
using namespace std;
//简历类
class Resume {
private:
string name;
string sex;
int age;
string timeArea;
string company;
public:
Resume(string name) {
this->name = name;
}
//设置个人信息
void SetPersonalInfo(string sex, int age) {
this->sex = sex;
this->age = age;
}
//设置工作经历
void SetWorkExperience(string timeArea, string company) {
this->timeArea = timeArea;
this->company = company;
}
//显示
void Display() {
cout << name << " " << sex << " " << age << endl;
cout << "工作经历:" << timeArea << company << endl;
}
};
//实现克隆简历
void test01()
{
Resume a = Resume("大鸟");
a.SetPersonalInfo("男", 29);
a.SetWorkExperience("1998-2000", "XX公司");
Resume b = Resume("大鸟");
b.SetPersonalInfo("男", 29);
b.SetWorkExperience("1998-2000", "XX公司");
Resume c = Resume("大鸟");
c.SetPersonalInfo("男", 29);
c.SetWorkExperience("1998-2000", "XX公司");
a.Display();
b.Display();
c.Display();
}
void test02()
{
Resume* a = new Resume("大鸟");
a->SetPersonalInfo("男", 29);
a->SetWorkExperience("1998-2000", "XX公司");
Resume* b = a;
Resume* c = a;
a->Display();
b->Display();
c->Display();
delete a;
delete b;
delete c;
}
int main()
{
test01();
cout << "-----------------------" << endl;
test02();
system("pause");
return 0;
}
test01 三份简历需要三次实例化,比较麻烦
test02 其实是传引用,而不是传值。这样做是在b、c纸上写着简历在a处一样,没有实际内容
原型模式
UML类图

代码实现
#include <iostream>
using namespace std;
//原型类
class Person {
public:
virtual Person* clone() = 0;
};
//简历类
class Resume : public Person {
private:
string name;
string sex;
int age;
string timeArea;
string company;
public:
Resume() {};
Resume(string name) {
this->name = name;
}
//设置个人信息
void SetPersonalInfo(string sex, int age) {
this->sex = sex;
this->age = age;
}
//设置工作经历
void SetWorkExperience(string timeArea, string company) {
this->timeArea = timeArea;
this->company = company;
}
//显示
void Display() {
cout << name << " " << sex << " " << age << endl;
cout << "工作经历:" << timeArea << " " << company << endl;
}
Person* clone() {
Resume* obj = new Resume();
*obj = *this;
return obj;
}
};
//客户端
void test()
{
Resume* a = new Resume("大鸟");
a->SetPersonalInfo("男", 29);
a->SetWorkExperience("1998-2000", "XX公司");
Resume* b = (Resume*)a->clone();
Resume* c = (Resume*)a->clone();
a->Display();
b->Display();
c->Display();
delete a;
delete b;
delete c;
}
int main()
{
test();
system("pause");
return 0;
}
只需要调用Clone方法就可以实现新简历的生成,并且可以再修改新简历的细节。等于是不用重新初始化对象,而是动态地获得对象运行时地状态。
一般在初始化的信息不发生变化的情况下,克隆是最好的办法。这既隐藏了对象创建的细节,又对性能是大大的提高。
浅复制
如果“简历”类当中有一个“设置工作经历”的方法,现实设计中,一般会再有一个“工作经历”类,当中有“时间区间”和“公司名称”等属性,“简历”类直接调用这个对象。
UML类图

代码实现
//简历的浅复制
#include <iostream>
#include <string>
using namespace std;
//原型类
class Person {
public:
virtual Person* clone() = 0;
};
//工作经历类
class WorkExperence {
public:
WorkExperence() {};
~WorkExperence() {};
WorkExperence(string workDate, string company) {
this->company = company;
this->workDate = workDate;
}
string workDate;
string company;
};
//简历类
class Resume : public Person {
private:
string name;
string sex;
int age;
WorkExperence* work;
public:
Resume() {};
Resume(string name) {
this->name = name;
work = new WorkExperence();
}
//设置个人信息
void SetPersonalInfo(string sex, int age) {
this->sex = sex;
this->age = age;
}
//设置工作经历
void SetWorkExperience(string workDate, string company) {
work->company = company;
work->workDate = workDate;
}
//显示
void Display() {
cout << name << " " << sex << " " << age << endl;
cout << "工作经历:" << work->workDate <<" " << work->company << endl;
}
Person* clone() {
Resume* obj = new Resume();
*obj = *this;
return obj;
}
};
//客户端
void test()
{
Resume* a = new Resume("大鸟");
a->SetPersonalInfo("男", 29);
a->SetWorkExperience("1998-2000", "AA公司");
Resume* b = (Resume*)a->clone();
b->SetWorkExperience("1998-2000", "BB公司");
Resume* c = (Resume*)a->clone();
c->SetWorkExperience("1998-2000", "CC公司");
a->Display();
b->Display();
c->Display();
delete a;
delete b;
delete c;
}
int main()
{
test();
system("pause");
return 0;
}
浅表复制对于值类型没有问题,对于引用类型,只是复制了引用,对引用的对象还是指向了原来的对象。
深复制
UML类图

代码实现
//简历的浅复制
#include <iostream>
#include <string>
using namespace std;
//原型类
class Person {
public:
virtual Person* clone() = 0;
};
//工作经历类
class WorkExperience : public Person {
public:
WorkExperience() {};
~WorkExperience() {};
WorkExperience(string workDate, string company) {
this->company = company;
this->workDate = workDate;
}
//深拷贝--拷贝构造函数,使用引用
WorkExperience(const WorkExperience& r) {
workDate = r.workDate;
company = r.company;
}
//“工作经历”类实现克隆方法
Person* clone() {
return new WorkExperience(*this); //调用拷贝构造函数
}
string workDate;
string company;
};
//简历类
class Resume : public Person {
private:
string name;
string sex;
int age;
WorkExperience* work;
public:
Resume() {};
Resume(string name) {
this->name = name;
work = new WorkExperience();
}
private:
Resume(WorkExperience* _work) {
//提供Clone方法调用的私有构造函数,以便克隆“工作经历”的数据
this->work = (WorkExperience*)_work->clone();
}
public:
//设置个人信息
void SetPersonalInfo(string sex, int age) {
this->sex = sex;
this->age = age;
}
//设置工作经历
void SetWorkExperience(string workDate, string company) {
work->company = company;
work->workDate = workDate;
}
//显示
void Display() {
cout << name << " " << sex << " " << age << endl;
cout << "工作经历:" << work->workDate << " " << work->company << endl;
}
Person* clone() {
//调用私有的构造方法,让“工作经历”克隆完成,然后再给这个“简历”对象的相关字段赋值
//最终返回一个深复制的简历对象
Resume* obj = new Resume(this->work);
obj->age = this->age;
obj->name = this->name;
obj->sex = this->sex;
return obj;
}
};
//客户端
void test()
{
Resume* a = new Resume("大鸟");
a->SetPersonalInfo("男", 29);
a->SetWorkExperience("1998-2000", "AA公司");
Resume* b = (Resume*)a->clone();
b->SetWorkExperience("1998-2000", "BB公司");
Resume* c = (Resume*)a->clone();
c->SetWorkExperience("1998-2000", "CC公司");
a->Display();
b->Display();
c->Display();
delete a;
delete b;
delete c;
}
int main()
{
test();
system("pause");
return 0;
}
浅复制中被复制的对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍指向原来的对象。深复制把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。

浙公网安备 33010602011771号