Chapter6—原型模式
原型模式
1 概念
原型的功能是将一个已经存在的对象作为源目标,其余对象都通过这个源目标创建。原型模式是指第二创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建中的其他细节。类对象的初次创建和再次创建可以通过拷贝来完成,拷贝又分为深拷贝和浅拷贝。发挥拷贝的作用,是原型模式的核心思想。这样做可以提高效率,避免多次创建对象造成的时间消耗。
2 意图(Intent)
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
3 动机(Motivate)
举一个简单的例子,我们都打印和复印的经历,如果我们需要多份相同的文件,我们一般将第一份文件打印出来,再用复印方式把这份文稿复印多份,这样做可以提升效率。那么对于第一份打印出来的原文稿,我们称之为"原型文件",而对于复印过程,我们则可以称之为"原型拷贝"。
4 类图结构
5 角色定义
- Prototype(原型接口):声明克隆方法
- ConcretePrototype(原型实现):原型接口的实现类
- Client(客户端):客户端只需要调用实现此接口的原型对象方法Clone(),便可以轻松得到一个全新的实例对象。
6 程序示例
汽车原型接口类
class BaseCar
{
public:BaseCar() = default;BaseCar(const string& strEngineName, const string& strColor, int nTireNumber);virtual ~BaseCar() = default;public:virtual BaseCar* Clone() = 0;protected:string m_strEngineName;string m_strColor;int m_nTireNumber;
};BaseCar::BaseCar(const string &strEngineName, const string &strColor, int nTireNumber)
{m_strEngineName = strEngineName;m_strColor = strColor;m_nTireNumber = nTireNumber;qDebug() << "安装车轮"; // 非常耗时Sleep(10);qDebug() << "车身喷漆";Sleep(10);qDebug() << "安装引擎";Sleep(10);
}
汽车原型实现类
class Car: public BaseCar
{
private:Car() = default;public:Car(const string& strEngineName, const string& strColor, int nTireNumber);~Car() = default;public:BaseCar* Clone() override;
};Car::Car(const string &strEngineName, const string &strColor, int nTireNumber):BaseCar(strEngineName, strColor, nTireNumber)
{}BaseCar *Car::Clone()
{BaseCar* pCar = new Car();*pCar = *this; // 拷贝return pCar;
}
客户端使用场景对比
void ClientTest()
{const int CAR_NUMBER = 500;std::vector<BaseCar*> vecCarA;std::vector<BaseCar*> vecCarB;// 非原型模式创建500个汽车,效率非常低下for (int i = 0; i != CAR_NUMBER; ++i)vecCarA.push_back(new Car("BMW", "Red", 4));// 原型模式创建500个汽车BaseCar* pPrototypeCar = new Car("BMW", "Red", 4);vecCarB.push_back(pPrototypeCar);for (int i = 0; i != CAR_NUMBER - 1; ++i)vecCarB.push_back(pPrototypeCar->Clone());// 释放内存for (int i = 0; i != CAR_NUMBER; ++i){delete vecCarA[i];delete vecCarB[i];}vecCarA.clear();vecCarB.clear();
}
7 思考小结
从类到对象叫做"创建",而由本体对象至副本对象则叫做"克隆",对于有非常复杂的初始化过程的对象需要消耗大量资源的情况,我们可以选择使用原型模式,但是C++中原型模式使用的比较少,因为C++本身是一门可以直接操作内存的语言,类的构造函数也有拷贝构造这一概念,我们只要掌握C++语言本身的深拷贝和浅拷贝实现机制,便可通过拷贝构造函数就能实现原型模式的效果。而原型模式更多的是在Java和C#等语言中,此类语言有虚拟机的概念,无法直接操作内存,这样的情况下使用原型模型的克隆,让虚拟机操作内存就会比new关键字快很多,从而提高效率。