原型模式
原型模式正是提供了自我复制的功能,就是说新对象的创建可以通过已有对象进行创建。《设计模式:可复用面向对象软件的基础》中是这样说的:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。这这个定义中,最重要的一个词是“拷贝”,也就是口头上的复制,而这个拷贝,也就是原型模式的精髓所在。
【注】深拷贝和浅拷贝的区别:
- 浅拷贝:就是给对象中的每个成员变量进行复制,就是把A1类中的变量直接赋给A2类中变量,属于值传递,但是涉及到有new之类内存分配的地方,他们却是共享内存的;
- 深拷贝:就是不仅使用值传递,而是要每个变量都有自己一份独立的内存空间,互不干扰;
- 默认的拷贝构造函数是浅拷贝的,如果要实现深拷贝,就需要重写拷贝构造函数T(const T&);
选择原型模式最好遵循以下原则:
- 当我们的对象类型不是开始就能确定的,而这个类型是在运行期确定的话,那么我们通过这个类型的对象克隆出一个新的对象比较容易一些;
- 有的时候,我们需要一个对象在某个状态下的副本,此时,我们使用原型模式是最好的选择;例如:一个对象,经过一段处理之后,其内部的状态发生了变化;这个时候,我们需要一个这个状态的副本,如果直接new一个新的对象的话,但是它的状态是不对的,此时,可以使用原型模式,将原来的对象拷贝一个出来,这个对象就和之前的对象是完全一致的了;
- 当我们处理一些比较简单的对象时,并且对象之间的区别很小,可能就几个属性不同而已,那么就可以使用原型模式来完成,省去了创建对象时的麻烦了;
- 有的时候,创建对象时,构造函数的参数很多,而自己又不完全的知道每个参数的意义,就可以使用原型模式来创建一个新的对象,不必去理会创建的过程;
即是说,基本就是你需要从A的实例得到一份与A内容相同,但是又互不干扰的实例的话,就需要使用原型模式!
优点
1.使用拷贝模式比直接new一个对象的开销要小的多;
2.可以在程序运行时(对象属性发生了变化),得到一份内容相同的实例,但之间还不会相互干扰;
示例:
#include "stdafx.h"
#include <iostream>
#include <cstring>
using namespace std;
class Product {
private:
string name;
int prize;
int size;
char* shape;
public:
Product(string n) { this->name = n; }
void setPrize(int prize) { this->prize = prize; }
void setSize(int size) { this->size = size; }
void setShape(char* shape) { this->shape = shape; }
void display() {
cout << "This Product name " << name.c_str() << endl \
<< " and the prize is " << this->prize << endl \
<< " and the size is " << this->size << " cm" << endl \
<< " and the shape is " << this->shape << endl;
}
Product* clone() {
Product* newProduct = new Product(name);
newProduct->setPrize(this->prize);
newProduct->setSize(this->size);
newProduct->setShape(this->shape);
return newProduct;
}
};
int main(int argc, char *argv[])
{
Product* p = new Product("apple");
p->setPrize(100);
p->setSize(10);
p->setShape("椭圆");
p->display();
Product* secProduct = p->clone();
secProduct->setShape("正方形");
secProduct->display();
system("pause");
return 0;
}
结果: