原型模式
概念
Prototype模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例。使用Prototype模式创建的实例,具有与原型一样的数据。
1)由原型对象自身创建目标对象。也就是说,对象创建这一动作发自原型对象本身。
2)目标对象是原型对象的一个克隆。也就是说,通过Prototype模式创建的对象,不仅仅与原型对象具有相同的结构,还与原型对象具有相同的值。
3)根据对象克隆深度层次的不同,有浅度克隆与深度克隆。
原型模式主要面对的问题是:“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是他们却拥有比较稳定一致的接口。
适用情况:
一个复杂对象,具有自我复制功能,统一一套接口。
特别说明
利用C++ 拷贝构造函数已经实现了原型模式的注意事项:
- 抽象类需要有纯虚函数:类内声明,类外初始化
- 浅拷贝:
*tmp = *this;
- 深拷贝:
IntelCPU *tmp = new IntelCPU(*this)
。 注意,这里使用具体类接收new出来的指针
拓展的类图
这里显示的是原型模式如何拓展代码
拷贝构造与原型模式
原型模式需要注意的是堆区内存的动态申请与释放,此处没有类图
抽象类
父类必须有虚析构函数
class CPU {
public:
virtual ~CPU() = 0; // 纯虚析构, 类内声明
// 拷贝接口
virtual CPU *clone() = 0;
virtual CPU *deepClone() = 0;
// 功能函数
virtual void printInfo() = 0;
virtual void setInfo(char *p) = 0;
virtual char *getInfo() = 0;
};
CPU::~CPU() { // 纯虚析构, 类外实现
// ...
}
具体类
重点部分
class IntelCPU : public CPU {
public:
// 构造函数
// 拷贝构造函数
IntelCPU(const IntelCPU &cpu) {
m_version = cpu.m_version;
m_year = cpu.m_year;
// 拷贝堆区内容
if (nullptr != cpu.m_info) {
m_info = new char[strlen(cpu.m_info) + 1];
strcpy(m_info, cpu.m_info);
} else {
m_info = nullptr;
}
}
// 重载构造函数
// 析构函数
~IntelCPU() {
if (m_info != nullptr) {
delete m_info;
m_info = nullptr;
}
}
// 实现拷贝接口
virtual CPU *clone() {
IntelCPU *tmp = new IntelCPU;
*tmp = *this; // = 浅拷贝
return tmp;
}
virtual CPU *deepClone() {
IntelCPU *tmp = new IntelCPU(*this);
return tmp;
}
// 功能函数
};
全部代码
class IntelCPU : public CPU {
public:
// 构造函数
IntelCPU() {
m_version = "";
m_year = 0;
m_info = nullptr;
}
// 拷贝构造函数
IntelCPU(const IntelCPU &cpu) {
m_version = cpu.m_version;
m_year = cpu.m_year;
// 拷贝堆区内容
if (nullptr != cpu.m_info) {
m_info = new char[strlen(cpu.m_info) + 1];
strcpy(m_info, cpu.m_info);
} else {
m_info = nullptr;
}
}
// 重载构造函数
IntelCPU(string version, int year) {
m_version = version;
m_year = year;
m_info = nullptr;
}
// 析构函数
~IntelCPU() {
if (m_info != nullptr) {
delete m_info;
m_info = nullptr;
}
}
// 实现拷贝接口
virtual CPU *clone() {
IntelCPU *tmp = new IntelCPU;
*tmp = *this; // = 浅拷贝
return tmp;
}
virtual CPU *deepClone() {
IntelCPU *tmp = new IntelCPU(*this);
return tmp;
}
// 功能函数
void setInfo(char *p) {
if (m_info != nullptr) {
delete m_info;
m_info = nullptr;
}
m_info = new char[strlen(p) + 1];
strcpy(m_info, p);
}
virtual char *getInfo() {
return m_info;
}
virtual void printInfo() {
cout << "m_version : " << m_version << " m_year : " << m_year << " m_info : " << m_info << endl;
}
private:
string m_version;
int m_year;
private:
char *m_info;
};
不使用拷贝构造函数实现深拷贝
virtual CPU *deepClone() {
IntelCPU *tmp = new IntelCPU();
tmp->m_version = this->m_version;
tmp->m_year = this->m_year;
// 拷贝堆区内容
if (nullptr != this->m_info) {
tmp->m_info = new char[strlen(this->m_info) + 1];
strcpy(tmp->m_info, this->m_info);
} else {
tmp->m_info = nullptr;
}
return tmp;
}
多态调用
CPU *cpu1 = new IntelCPU("第一代", 2); // 这里是多态调用
cpu1->setInfo("第一代CPU");
CPU *cpu2 = cpu1->deepClone(); // 深拷贝
cpu1->setInfo("第一代CPU升级了 ... ");
cout << "打印cpu1..." << endl;
cpu1->printInfo();
cout << "打印cpu2..." << endl;
cpu2->printInfo();
if (nullptr == cpu1) {
delete cpu1;
cpu1 = nullptr;
}
if (nullptr == cpu2) {
delete cpu2;
cpu2 = nullptr;
}
直接调用拷贝构造
IntelCPU *cpu1 = new IntelCPU("8550", 2); // 这里是调用拷贝构造函数
cpu1->setInfo("第一代CPU");
IntelCPU *cpu2 = new IntelCPU(*cpu1);
cpu1->setInfo("第一代CPU升级了");
cout << "打印cpu1..." << endl;
cpu1->printInfo();
cout << "打印cpu2..." << endl;
cpu2->printInfo();
if (nullptr == cpu1) {
delete cpu1;
cpu1 = nullptr;
}
if (nullptr == cpu2) {
delete cpu2;
cpu2 = nullptr;
}