什么是原型模式?
先来看个例子:每年的校园招聘的时候,许多好公司来学校招应届生,大家就要去投简历,我相信大家都是聪明人,先写好一份原始简历,拿去复印n多份,然后去参加宣讲会投简历,投完简历后,第二天发现要简历写牛B点,就去修改原始简历,然后再去打印n多份就可以了。其中原始简历就是原型模式中的原型。
那么原型的模式意图呼之欲出:用原型实例指定创建对象的种类,并且通过拷贝(复制)这些原型创建新的对象。
在GOF的《设计模式:可复用面向对象软件的基础》中是这样说的:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。这这个定义中,最重要的一个词是“拷贝”,也就是口头上的复制,而这个拷贝,也就是原型模式的精髓所在。
#include <iostream>
using namespace std;
class Prototype
{
public:
Prototype(){}
~Prototype(){}
virtual Prototype *clone() = 0;
};
class ConcretePrototypeA :public Prototype
{
public:
ConcretePrototypeA() :member(0){}
~ConcretePrototypeA(){}
ConcretePrototypeA(const ConcretePrototypeA &rhs)
{
member = rhs.member;
}
virtual ConcretePrototypeA* clone()
{
cout << "copy of self" << endl;
return new ConcretePrototypeA(*this);
}
private:
int member;
};
int main(int argc, char **argv)
{
//生成对像
ConcretePrototypeA *conPro = new ConcretePrototypeA();
//复制自身
ConcretePrototypeA * conPro1 = conPro->clone();
//复制自身
ConcretePrototypeA * conPro2 = conPro->clone();
delete conPro;
conPro = NULL;
delete conPro1;
conPro1 = NULL;
delete conPro2;
conPro2 = NULL;
return 0;
}
上述代码实现了一个最简单的原型模式,但是已经将原型模式的基本实现原理展现出来了。而有的时候,当调用Clone获得了一个复制的对象以后,需要改变对象的状态,此时就可能需要在ConcretePrototype类中添加一个Initialize操作,专门用于初始化克隆对象。由于在clone的内部调用的是复制构造函数,而此处又涉及到深复制和浅复制的问题。所以,在实际操作的过程中,这些问题,都需要进行仔细的考虑。
来看一个稍微复杂点的例子:类含有指针成员,这里就涉及到了拷贝构造函数的深拷贝。其实这里例子还需要一个拷贝复制函数,很简单,就是要考虑到自赋值的情况就可以了。
#include <iostream>
using namespace std;
class Resume
{
public:
Resume(){}
virtual Resume* clone() =0;
virtual void show() {};
virtual ~Resume(){}
protected:
char*name;
};
class ResumeA : public Resume
{
public:
ResumeA(){}
ResumeA(const char *str) //构造函数
{
if (str == NULL)
{
name = new char[1];
name[0] = '\0';
}
else
{
name = new char[strlen(str) + 1];
strcpy(name, str);
}
}
ResumeA(const ResumeA &rhs) //拷贝构造函数
{
name = new char[strlen(rhs.name) + 1];
strcpy(name, rhs.name);
}
ResumeA& operator=(const ResumeA& rhs)
{
if (this == &rhs)
return *this;
delete[] name;
int len = strlen(rhs.name);
name = new char[len + 1];
strcpy(name, rhs.name);
return *this;
}
ResumeA* clone() override
{
cout << "ResumeA name : " << name << endl;
return new ResumeA(this->name);
}
~ResumeA()
{
delete[] name;
}
};
int main()
{
Resume *r = new ResumeA("a");
Resume *r1 = r->clone();
delete r1;
r1 = NULL;
}
总结: