原型模式
设计模式
Prototype模式是一对象创建型模式,它采取复制原型对象的方法来创建对象的实例。使用 Prototype模式创建的实例,具有与原型一样的数据。
1) 由原型对象自身创建目标对象。也就是说,对象创建这一动作发自原型对象本身。
2) 目标对象是原型对象的一个克隆。也就是说,通过 Prototype模式创建的对象,不仅仅与
原型对象具有相同的結构,还与原型对象具有相同的值。
3) 根据对象克隆深度层次的不同,有浅度克隆与深度克隆。
Prototype模式提供了一个通过已存在对象进行新对象创建的接口(Clone), Clone()实现和具体的实现语言相关,在C++中我们将通过拷贝构造函数实现之。
原型模式主要面对的问题是:“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是他们却拥有比较稳定一致的接口。
适用情况:
一个复杂对象,具有自我复制功能,统一一套接口。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| #include <iostream> #include <string> #include <string.h>
using namespace std;
class Person { public: virtual Person* clone() = 0; virtual void printT() = 0;
protected: private: };
class CppProgrammer:public Person { public: CppProgrammer() { m_name = ""; m_age = 0; m_ptr = "aaaa"; }; CppProgrammer(string name, int age) { m_name = name; m_age = age; m_ptr = "aaaa"; }; void setPtr(char* p) { if(m_ptr != NULL) { delete m_ptr; } m_ptr = new char[strlen(p) + 1]; strcpy(m_ptr, p); } virtual void printT() { cout << "name:" << m_name << endl; cout << "age:" << m_age << endl; if(m_ptr != NULL){ printf(m_ptr); printf("\n"); } }; virtual Person* clone() { CppProgrammer* tmp = new CppProgrammer(); *tmp = *this; return tmp; }; CppProgrammer operator=(CppProgrammer& tmp) { cout << "my=" << endl; m_name = tmp.m_name; m_age = tmp.m_age; if(tmp.m_ptr == NULL) { m_ptr = NULL; } else { m_ptr = new char(strlen(tmp.m_ptr) + 1); strcpy(m_ptr, tmp.m_ptr); } return *this; }; protected: private: string m_name; int m_age; char* m_ptr; };
int main() { Person* c1 = new CppProgrammer("Tom", 12); c1->printT();
Person* c2 = c1->clone(); c2->printT();
delete c1; c2->printT(); cout << "Hello world!" << endl; return 0; }
|
输出:
1 2 3 4 5 6 7 8 9 10 11
| name:Tom age:12 aaaa my= name:Tom age:12 aaaa name:Tom age:12 aaaa Hello world!
|
注意
需要注意clone函数中只是进行了类的浅拷贝,如果类的成员有指针的话,此时拷贝过去的也只是指针所指向的地址的值。所以需要重新定义赋值函数(或者定义复制构造函数)。
指针的深拷贝代码如下:
1 2 3 4 5 6 7 8 9
| if(tmp.m_ptr == NULL) { m_ptr = NULL; } else { m_ptr = new char(strlen(tmp.m_ptr) + 1); strcpy(m_ptr, tmp.m_ptr); }
|