写在前面
我们知道,设计模式的终极目标是高内聚,低耦合,好的软件代码必然离不开好的设计。最近在学习设计模式这块的内容,参考的书籍是程杰的《大话设计模式》,这本书对于初学者来说比较友好,易上手,博客里的内容是参考本书以及网络资源整理的。
博客更新基本上是边学边写的过程,写这个专题一是为了作为自己的知识备忘,二是希望能给正在学习设计模式的童鞋一些参考,博客中内容有纰漏或错误之处,还请指出,谢谢。
基本定义
原型模式,属于创建型模式。原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
PS:原型模式,提供了对象拷贝的Clone接口,而在C++中,拷贝构造函数作为对象拷贝的一种实现方式。
UML图
原型模式总体结构比较简单,主要由抽象原型类和具体原型类组成。
包含以下几类角色:
Prototype:抽象原型类(一般可定义为接口),声明一个克隆自身的接口。
ConcretePrototype:具体原型类,实现一个克隆自身的操作。
原型模式实例
场景:制作多份简历时,每份简历的内容存在些许差别,此时可以用到原型模式。
UML图
代码实现
1. Object抽象原型类
// 抽象原型类,Object
class Object
{
public:
virtual Object* Clone() = 0;
};
2. 具体原型类--简历类
// 工作经历类
class Experience
{
public:
std::string m_workDate;
std::string m_company;
};
//简历类(具体原型类),Resume
class Resume : public Object
{
public:
Resume(string name, int age)
{
m_name = name;
m_age = age;
m_experience = new Experience();
}
//深拷贝构造函数,若不写则为默认拷贝构造函数,默认拷贝构造函数为浅拷贝。
Resume(const Resume& resume)
{
m_name = resume.m_name;
m_age = resume.m_age;
m_experience = new Experience();
m_experience->m_company = resume.m_experience->m_company;
m_experience->m_workDate = resume.m_experience->m_workDate;
}
~Resume()
{
if (m_experience != NULL) {
delete m_experience;
}
}
void SetPersonalInfo(std::string name, int age)
{
m_name = name;
m_age = age;
}
void SetExperience(std::string workDate, std::string company)
{
m_experience->m_company = company;
m_experience->m_workDate = workDate;
}
void Display()
{
std::cout << m_name << " " << m_age << std::endl;
std::cout << "Experience: " << m_experience->m_workDate << " " <<m_experience->m_company << std::endl;
}
Object* Clone()
{
return new Resume(*this);
}
public:
std::string m_name;
int m_age;
Experience* m_experience = NULL;
};
注:这里为了访问方便,成员变量设置成public,实际应该设置为protected/private。
3. 客户端测试代码
int main(int argc, char* argv[])
{
Resume *resume1 = new Resume("ZZQ", 25);
resume1->SetExperience("2017-7~2020-7", "Tsinghua University");
Resume *resume2 = dynamic_cast<Resume*>(resume1->Clone());
resume2->SetExperience("2020-7~2021-7", "Baidu.com, Inc");
resume1->Display();
resume2->Display();
return 0;
}
测试结果
D:\Project\code_exercise\cmake-build-debug\code_exercise.exe
ZZQ 25
Experience: 2017-7~2020-7 Tsinghua University
ZZQ 25
Experience: 2020-7~2021-7 Baidu.com, Inc
Process finished with exit code 0
优缺点和使用场景
优点:
1、提高性能 : 原型模式克隆实例对象 , 比使用构造函数重新创建对象性能要高 ( 针对类实例对象开销大的情况 )。
2、简化流程: 原型模式简化了创建实例的过程 ,隐藏创建细节, 可以直接修改现有的对象实例的值 , 达到复用的目的 ( 针对构造函数繁琐的情况 )。
缺点:
1、需要重写clone方法,并且对于复杂场景,要能熟练掌握深拷贝和浅拷贝的区别。
使用场景:
1、当使用类构造函数进行初始化时,当初始化流程出现繁琐,资源占用,耗时等情况时,可以使用原型模式克隆实例。
2、当实例化对象数量庞大时可以使用原型模式。