2016-07-21
(www.cnblogs.com/icmzn)
模式理解
1. Prototype 原型模式定义
提供了类的自我复制的能力,即通过已有对象进行新对象的创建。因为原型模式实在内存中进行二进制流的拷贝,
所以比直接通过new 一个对象性能好。不同的实现方式与具体的语言相关。
2. 原型模式的优点
(1)性能优良,实在内存中基于二进制的拷贝
(2)在进行原型模式的时候,并不通过构造函数。
3. 原型模式的适用场景
(1)需要根据已有对象创建大量的对象;
(2)某个对象的创建需要有大量的前期准备,需要等待其他模块准备完毕;
(3)把相同的对象付给其他对象处理。
4. 原型模式的讨论与注意问题
(1)原型模式注意浅层拷贝与深层拷贝
语言基础类型浅层拷贝,指针、引用浅层拷贝只传递地址内容需要注意
C++:需要依赖类的复制构造函数实现
(2)这就是需要提到对象的复制问题
* 类成员是new 多态创建的类成员,要进行深层拷贝,同时要在~XX析构函数中进行析构处理。
* 当记性赋值操作是即=(),右边是一个临时由于运算产生的临时对象,则可以执行高效的赋值操作,即将成员指正直接指向“临时对象”内的成员地址位置,
然后,将“临时对象”的成员指针设置为nullptr,即可。《移动赋值构造》
原型:
CXXObject(const CXXObject && LinShi)
{//移动构造函数
m_pName = Linshi.m_pName;
LinShi.m_pName = nullptr;
}
(3)实际上,Prototype, Builder, Abstract Factory都是通过一个类(对象) 来创建其他类
但是,他们之间有侧重之分。
builder 侧重对象的构建过程,并不直接返回类对象,由监管者Director协调具体的Builder类分别根据不同的构建过程创建对象;
Abstract Factory 侧重于具体的工厂创建本类型的不同对象,并且是直接返回对象;
Prototye 侧重根据一个对象返回这个对象的副本,必须注意深度拷贝。
程序实现(C++)
Prototype.h
1 #pragma once 2 3 #include <string> 4 #include <iostream> 5 #include <vector> 6 class CAbsPrototype 7 { 8 public: 9 CAbsPrototype(); 10 ~CAbsPrototype(); 11 public: 12 virtual CAbsPrototype* clone() const; 13 }; 14 15 16 class CConcentPrototype : public CAbsPrototype 17 { 18 private: 19 //语言基础类型浅层拷贝,指针、引用浅层拷贝只传递地址内容需要注意 20 int m_iAge; 21 char* m_pName;//深层拷贝,构造冲初始化,系统中保持协调洗头 22 std::vector<double> m_dScores; 23 24 25 public: 26 // 注意,没有默认值得形参需要排在有默认值的前面,必然的原因 27 CConcentPrototype(const std::vector<double>& socresV, const char* aName = "Default Name", int age = 18) :m_iAge(age) 28 { 29 m_pName = nullptr; 30 31 int l = strlen(aName) + 1; 32 m_pName = new char[l]; 33 strcpy_s(m_pName, l, aName); 34 35 //m_dScores.reserve(socresV.size()); 36 m_dScores = socresV; 37 std::cout << "一般构造函数执行。" << std::endl; 38 } 39 ~CConcentPrototype() 40 { 41 delete[] m_pName; 42 } 43 CConcentPrototype(const CConcentPrototype& obj)//复制构造函数 44 { 45 m_iAge = obj.m_iAge; 46 47 int l = strlen(obj.m_pName) + 1; 48 m_pName = new char[l]; 49 strcpy_s(m_pName, l, obj.m_pName); 50 51 m_dScores.clear(); 52 m_dScores = obj.m_dScores; 53 std::cout << "复制构造函数执行。" << std::endl; 54 } 55 //要考虑深层拷贝与浅层拷贝 56 CAbsPrototype* clone() const override; 57 void outPut() 58 { 59 std::cout << m_pName << m_iAge << " score:"; 60 61 for (auto t : m_dScores) 62 std::cout << t << " "; 63 std::cout << std::endl; 64 } 65 66 };
Prototype.cpp
1 #include "AbsPrototype.h" 2 3 4 CAbsPrototype::CAbsPrototype() 5 { 6 } 7 CAbsPrototype::~CAbsPrototype() 8 { 9 } 10 11 CAbsPrototype* CAbsPrototype::clone() const 12 { 13 return nullptr; 14 } 15 16 17 // 18 CAbsPrototype* CConcentPrototype::clone() const 19 { 20 //利用复制搞糟函数实现 Prototype 模式 21 CConcentPrototype* p = new CConcentPrototype(*this); 22 return p; 23 //子类指针,赋值给父类指针,在调用处转化为子类指针 24 }
(1)模板应用
main.cpp
1 // Prototype.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include "AbsPrototype.h" 6 #include <iostream> 7 8 9 int _tmain(int argc, _TCHAR* argv[]) 10 { 11 std::vector<double> scores{11.2, 33.4, 45.6, 99.9}; 12 CConcentPrototype* pObj = new CConcentPrototype(scores, "zhongguo", 26); 13 pObj->outPut(); 14 15 std::cout << "-----------------" << std::endl; 16 for (int i = 0; i < 10; i++) 17 { 18 CConcentPrototype* pTem = (CConcentPrototype*)pObj->clone(); 19 pTem->outPut(); 20 } 21 22 system("pause"); 23 return 0; 24 }
(2)输出展示