本文介绍设计模式中的原型模式。
本质上其实就是克隆。
下面以个人简历为例进行举例说明:
深拷贝版本:
#include <iostream>
#include <string>
#include <memory>
using namespace std;
template<class T>
class ICloneable
{
public:
virtual T* clone() = 0;
};
class CWorkExperience
{
public:
CWorkExperience(){}
CWorkExperience(const string& company,
const string& workTime)
{
m_strCompany = company;
m_strWorkTime = workTime;
}
CWorkExperience(const CWorkExperience& right)
{
m_strCompany = right.m_strCompany;
m_strWorkTime = right.m_strWorkTime;
}
~CWorkExperience()
{
cout << "CWorkExperience析构" << endl;
printInfo();
}
void setCompany(const string& company)
{
m_strCompany = company;
}
const string& getCompany() const
{
return m_strCompany;
}
void setWorkTime(const string& workTime)
{
m_strWorkTime = workTime;
}
const string& getWorkTime() const
{
return m_strWorkTime;
}
void printInfo()
{
cout << "Company: " << m_strCompany << endl;
cout << "WorkTime: " << m_strWorkTime << endl;
}
private:
string m_strCompany; // company name
string m_strWorkTime; // work time
};
// 简历类
class CResume : public ICloneable<CResume>
{
public:
CResume(){}
~CResume()
{
cout << "CResume析构 " << m_name << endl;
}
void setInfo(const string& name, const string& sex
, int age)
{
m_name = name;
m_sex = sex;
m_age = age;
}
void setExperience(const string& company, const string& workTime)
{
m_experience.setCompany(company);
m_experience.setWorkTime(workTime);
}
CResume* clone()
{
CResume* resume = new CResume;
resume->setInfo(m_name, m_sex, m_age);
resume->setExperience(m_experience.getCompany(), m_experience.getWorkTime());
return resume;
}
void printInfo()
{
cout << "Name: " << m_name << endl;
cout << "Sex: " << m_sex << endl;
cout << "Age: " << m_age << endl;
cout << "Experience: " << endl;
m_experience.printInfo();
cout << endl;
}
protected:
string m_name;
string m_sex;
int m_age;
CWorkExperience m_experience;// 对象
};
void testPrototype()
{
CResume re;
re.setInfo("Jacky", "Male", 20);
re.setExperience("MS", "2001.11 - 2005.11");
re.printInfo();
CResume* pClone = re.clone();
pClone->setInfo("Marry", "Female", 30);
pClone->setExperience("Google", "2006.01 - 2010.01");
pClone->printInfo();
delete pClone;
pClone = NULL;
}
int main(void)
{
testPrototype();
return 0;
}
运行结果如下:
#include <iostream>
#include <string>
#include <memory>
using namespace std;
// 克隆接口
template<class T>
class ICloneable
{
public:
virtual T* clone() = 0;
};
// 工作经历类
class CWorkExperience
{
public:
CWorkExperience(){}
CWorkExperience(const string& company,
const string& workTime)
{
m_strCompany = company;
m_strWorkTime = workTime;
}
CWorkExperience(const CWorkExperience& right)
{
m_strCompany = right.m_strCompany;
m_strWorkTime = right.m_strWorkTime;
}
~CWorkExperience()
{
cout << "CWorkExperience析构" << endl;
printInfo();
}
void setCompany(const string& company)
{
m_strCompany = company;
}
const string& getCompany() const
{
return m_strCompany;
}
void setWorkTime(const string& workTime)
{
m_strWorkTime = workTime;
}
const string& getWorkTime() const
{
return m_strWorkTime;
}
void printInfo()
{
cout << "Company: " << m_strCompany << endl;
cout << "WorkTime: " << m_strWorkTime << endl;
}
private:
string m_strCompany; // company name
string m_strWorkTime; // work time
};
// 简历类
class CResume : public ICloneable<CResume>
{
private:
// 只允许调用带参数的构造函数和拷贝构造函数
CResume(){m_experience = NULL;}
public:
// 带参构造函数
CResume(CWorkExperience* pWorkExperience)
{
// 不负责内存分配 只是共享
m_experience = pWorkExperience;
}
// 带参拷贝构造函数
CResume(const CResume& right)
{
m_name = right.m_name;
m_sex = right.m_sex;
m_age = right.m_age;
// 注意这里是指针赋值 属于浅拷贝
m_experience = right.m_experience;
}
~CResume()
{
cout << "CResume析构 " << m_name << endl;
}
void setInfo(const string& name, const string& sex
, int age)
{
m_name = name;
m_sex = sex;
m_age = age;
}
void setExperience(const string& company, const string& workTime)
{
m_experience->setCompany(company);
m_experience->setWorkTime(workTime);
}
CResume* clone()
{
// 调用拷贝构造函数 浅拷贝
CResume* resume = new CResume(*this);
return resume;
}
void printInfo()
{
cout << "Name: " << m_name << endl;
cout << "Sex: " << m_sex << endl;
cout << "Age: " << m_age << endl;
cout << "Experience: " << endl;
m_experience->printInfo();
cout << endl;
}
protected:
string m_name;
string m_sex;
int m_age;
CWorkExperience* m_experience;// 指针 聚合
};
void testPrototype()
{
CWorkExperience* pWorkExperience = new CWorkExperience("MS", "2001.11 - 2005.11");
CResume re(pWorkExperience); // 只能这样构造 无参构造被屏蔽掉了
re.setInfo("Jacky", "Male", 20);
re.printInfo();
CResume* pClone = re.clone(); // 指针赋值 浅拷贝
//delete pWorkExperience; // 这里如果调用delete 程序会崩溃(因为是共享)
pClone->setInfo("Marry", "Female", 30);
pClone->setExperience("Google", "2006.01 - 2010.01");
pClone->printInfo();
re.printInfo(); // 我们发现原对象的workExperience属性已经被修改
delete pClone;
delete pWorkExperience;
pClone = NULL;
pWorkExperience = NULL;
}
int main(void)
{
testPrototype();
return 0;
}
运行结果如下:
将146行取消注释 程序崩溃。
运行图如下:(图片请在新窗口中查看)
接下来一篇文章解决指针共享的深度拷贝版本。