什么是原型模式?
原型模式(Prototype)是指 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
说白了,就是从一个对象创建另外一个同类型的可定制的对象,并且创建的过程隐藏了创建的细节。使得客户端在创建多个对象时更为简洁。 当一个类的构建比较复杂,而我们需要动态的进行创建,只有部分数据需要定制时,原型模式可以在隐藏创建细节的同时很好的确保代码的简洁。
举个例子
对于同班的同学,具有一些共同的属性,例如同一所学校,同一个专业等,如果我们需要动态的创建多个学生的实例,由于大部分的属性信息都是相同的,没有必要对每个实例进行创建,使用原型模式创建一个副本,并进行定制即可。 示例代码:
1. Prototype.h
#ifndef Prototype_h__
#define Prototype_h__
#include <string>
using namespace std;
/*
* Prototype interface
*/
class IPrototype
{
public:
virtual IPrototype* Clone() = 0;
};
struct COrganizeInfo
{
string m_strSchool;
string m_strMajor;
};
class CStudent : IPrototype
{
public:
CStudent();
~CStudent();
virtual IPrototype* Clone();
void SetName(const string& name) { m_strName = name; }
void SetOrganizeInfo(COrganizeInfo* pOrgInfo) {m_pOrgInfo = pOrgInfo;}
void PrintInfo();
private:
string m_strName;
COrganizeInfo* m_pOrgInfo;
};
#endif // Prototype_h__
2. Prototype.cpp
#include "Prototype.h"
#include <iostream>
CStudent::CStudent(): m_strName(""),m_pOrgInfo(NULL)
{
}
CStudent::~CStudent()
{
delete m_pOrgInfo;
}
IPrototype* CStudent::Clone()
{
CStudent* pStudent = new CStudent();
//deep copy
COrganizeInfo* pOrgInfo = new COrganizeInfo();
pOrgInfo->m_strSchool = m_pOrgInfo->m_strSchool;
pOrgInfo->m_strMajor = m_pOrgInfo->m_strMajor;
pStudent->SetOrganizeInfo(pOrgInfo);
pStudent->SetName(m_strName);
return pStudent;
}
void CStudent::PrintInfo()
{
cout << "Student:" << m_strName
<< ", School:" << m_pOrgInfo->m_strSchool
<< ", Major:" << m_pOrgInfo->m_strMajor << endl;
}
3. Client
COrganizeInfo* pOrgInfoA = new COrganizeInfo();
pOrgInfoA->m_strSchool = "School XXX";
pOrgInfoA->m_strMajor = "CS";
CStudent* pStudentA = new CStudent();
pStudentA->SetOrganizeInfo(pOrgInfoA);
pStudentA->SetName("nameA");
pStudentA->PrintInfo();
CStudent* pStudentB = (CStudent*)pStudentA->Clone();
pStudentB->SetName("nameB");
pStudentB->PrintInfo();
CStudent* pStudentC = (CStudent*)pStudentA->Clone();
pStudentC->SetName("nameC");
pStudentC->PrintInfo();
从client 的示例代码可以看出, studentB 和 studentC 对象的创建直接通过 Clone() 进行创建,只需要更改必要的数据(name)便完成了新对象的创建初始化工作。如果我们不使用原型模式,client 端的代码类似下面所示:
COrganizeInfo* pOrgInfoA = new COrganizeInfo();
pOrgInfoA->m_strSchool = "School XXX";
pOrgInfoA->m_strMajor = "CS";
CStudent* pStudentA = new CStudent();
pStudentA->SetOrganizeInfo(pOrgInfoA);
pStudentA->SetName("nameA");
pStudentA->PrintInfo();
COrganizeInfo* pOrgInfoB = new COrganizeInfo();
pOrgInfoB->m_strSchool = "School XXX";
pOrgInfoB->m_strMajor = "CS";
CStudent* pStudentB = new CStudent();
pStudentB->SetOrganizeInfo(pOrgInfoA);
pStudentB->SetName("nameB");
pStudentB->PrintInfo();
通过对比可以看出,一般在初始化的信息不怎么发生变化的情况下,克隆是最好的办法。