一,简介
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。
二,角色
Prototype
原型类,生命一个克隆自身的接口
ConcretePrototype
具体原型类,实现一个克隆自身的操作
三,举例
创建两个Prototype对象,并对内部char* str分别赋值。
1,类图
2,代码
class Prototype {//原型类
private:
string id;
char* str;
public:
virtual ~Prototype() {
delete[] str;
}
virtual Prototype*Clone() = 0;
Prototype(string i, char*s) {
id = i;
int len = strlen(s);
str = new char[len + 1];//深度复制
cout << &str << endl;//输出地址 作为对比
strcpy(str,s);
str[len] = '\0';
}
string getId() { return id; }
char* getStr() { return str; }
};
class ConcretePrototype1 :public Prototype {//具体原型类
public:
ConcretePrototype1(string id,char*s):Prototype(id,s){}
ConcretePrototype1(ConcretePrototype1& cp1):Prototype(cp1.getId(),cp1.getStr())// 复制构造函数,实现深度复制
{
}
virtual Prototype* Clone() {
return new ConcretePrototype1(*this);
}
};
char* s = "hello";
Prototype* p = new ConcretePrototype1("1", s);
Prototype* c = p->Clone();
cout << c->getId() << endl;
cout << c->getStr() << endl;
delete p;
delete c;
四,优缺点
优点: 1、性能提高。 2、逃避构造函数的约束
缺点: 配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。
五,使用场景
1.当我们的对象类型不是开始就能确定的,而这个类型是在运行期确定的话,那么我们通过这个类型的对象克隆出一个新的对象比较容易一些;
2.有的时候,我们需要一个对象在某个状态下的副本,此时,我们使用原型模式是最好的选择;例如:一个对象,经过一段处理之后,其内部的状态发生了变化;这个时候,我们需要一个这个状态的副本,如果直接new一个新的对象的话,但是它的状态是不对的,此时,可以使用原型模式,将原来的对象拷贝一个出来,这个对象就和之前的对象是完全一致的了;
3.当我们处理一些比较简单的对象时,并且对象之间的区别很小,可能就几个属性不同而已,那么就可以使用原型模式来完成,省去了创建对象时的麻烦了;
4.有的时候,创建对象时,构造函数的参数很多,而自己又不完全的知道每个参数的意义,就可以使用原型模式来创建一个新的对象,不必去理会创建的过程。
->适当的时候考虑一下原型模式,能减少对应的工作量,减少程序的复杂度,提高效率。
注意:原型模式 通俗地说就是克隆,就是复制一个对象的实例 . 那么,它当然可以用对象的拷贝构造函数来实现,但是 拷贝构造函数 却不是 原型模式 的全部。两者不是一个概念。
如:细胞分裂