**定义:**原型模式(Prototype Pattern),用原型模式指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
**类型:**创建型模式。
**类图:**
![](https://box.kancloud.cn/2016-08-19_57b6abd340b2b.jpg)
**参与角色**:
1. CPrototype,抽象原型基类,提供一个Clone的接口以及一些设置显示的接口。
1. CConcretePrototype,声明定义原型的相关参数,并实现Clone接口,主要是通过实现拷贝构造函数来完成的。
另外实现其他接口。
1. Client,首先定义一个原型对象,然后以此为原型克隆新的对象。
**概述:**
如果只是为了更快的完成新对象的生成,其实就没必要使用原型模式了。因为可以直接使用拷贝构造函数即可。而使用原型模式最重要的原因是隔离Client去了解具体的实现类,降低模块间的耦合。Client只需要知道一个抽象类的指针,不仅可以操作具体各咱方法,另外也还可以生成新的对象。
另外,使用拷贝构造函数时,需要注意深拷贝及浅拷贝。浅拷贝,即按位进行拷贝,即两个对象的每一个成员变量是相同的。深拷贝,自定义拷贝,一般会处理指针,引用等类型,保证它们有相同的值,而不是它们本身相同。
有一批Thinkpad电脑,除了内存和硬盘容量外,其他配置都相同。我们可以通过原型对象生成新的对象,并且不需要知道具体的实现类名。
**代码:**
// 提供接口
~~~
class CPrototype
{
public:
virtual CPrototype* Clone() = 0;
virtual void Show() = 0;
virtual void SetRam(int _nRam) = 0;
virtual void SetRom(int _nRom) = 0;
};
~~~
// 电脑的基本配置信息类
~~~
class CComputerConfig : public CPrototype
{
public:
CComputerConfig(char* _szName, int _nRomSize, int _nRamSize) : m_nRomSize(_nRomSize), m_nRamSize(_nRamSize)
{
if (NULL != _szName)
{
size_t nSize = strlen(_szName) + 1;
m_szComputerName = new char[nSize];
strcpy_s(m_szComputerName, nSize, _szName);
}
else
{
m_szComputerName = NULL;
}
}
~CComputerConfig()
{
if (NULL != m_szComputerName)
{
delete m_szComputerName;
}
}
CComputerConfig(const CComputerConfig& _other)
{
if (NULL == _other.m_szComputerName)
{
m_szComputerName = NULL;
}
else
{
size_t nSize = strlen(_other.m_szComputerName) + 1;
m_szComputerName = new char[nSize];
strcpy_s(m_szComputerName, nSize, _other.m_szComputerName);
m_nRomSize = _other.m_nRomSize;
m_nRamSize = _other.m_nRamSize;
}
}
virtual CPrototype* Clone()
{
return new CComputerConfig(*this);
}
virtual void Show()
{
cout<<m_szComputerName<<",Ram "<<m_nRamSize<<",Rom "<<m_nRomSize<<endl;
}
virtual void SetRam(int _nRam)
{
m_nRamSize = _nRam;
}
virtual void SetRom(int _nRom)
{
m_nRomSize = _nRom;
}
public:
char* m_szComputerName;
int m_nRomSize;
int m_nRamSize;
};
~~~
// 客户端
~~~
int _tmain(int argc, _TCHAR* argv[])
{
// ThindPad系列电脑
CComputerConfig computer("Thinkpad", 500, 2);
// 原型
CPrototype* pPrototype = &computer;
pPrototype->Show();
// ThindPad系列的2G内存版,500G硬盘版
CPrototype* p2GComputer = computer.Clone();
p2GComputer->SetRam(4);
p2GComputer->Show();
// 4G内存,1T硬盘版
CPrototype* p1TCompter = computer.Clone();
p1TCompter->SetRam(8);
p1TCompter->SetRom(1024);
p1TCompter->Show();
return 0;
}
~~~
**使用场合:**
1. 两个模块A,B,模块B对外暴露一个对象C指针。而模块A需要建立很多很多C的对象,但是不需要知道具体的C是如何创建的。这个时候就应该使用原型模式。
优缺点:
1. 优点,能够降低模块间的耦合性,另外能够快速的创建新对象。
缺点,改造一个已有类型时,需要细心考虑所有成员变量拷贝的问题,容易遗漏造成错误。
**参考资料:**
1. 《设计模式——可复用面向对象软件基础》
1. 《Java与模式》
1. 《大话设计模式》
- 前言
- 设计模式六大原则
- 1——创建型模式之简单工厂模式
- 2——创建型模式之工厂方法模式
- 3——创建型模式之抽象工厂模式
- 4——创建型模式之单例模式
- 5——创建型模式之建造者模式
- 6——创建型模式之原型模式
- 7——结构型模式之适配器模式
- 8——结构型模式之桥接模式
- 9——结构型模式之组合模式
- 10——结构型模式之装饰者模式
- 11——结构型模式之外观模式
- 12——结构型模式之享元模式
- 13——结构型模式之代理模式
- 14——行为型模式之职责链模式
- 15——行为型模式之命令模式
- 16——行为型模式之解释器模式
- 17——行为型模式之迭代器模式
- 18——行为型模式之中介者模式
- 19——行为型模式之备忘录模式
- 20——行为型模式之观察者模式
- 21——行为型模式之状态模式
- 22——行为型模式之策略模式
- 23——行为型模式之模板方法模型
- 24——行为型模式之访问者模式
- 设计模式总结