文章目录
- 原型模式
- 结构
- 实现
- 特点
原型模式
原型模式是软件开发中的一种创造设计模式。当要创建的对象类型由原型实例确定时使用,该实例被克隆以生成新对象。使用原型实例指定要创建的对象的种类,并通过复制此原型来创建新对象。
首先,应该注意原型模式不是用来获得性能优势的。它仅用于从原型实例创建新对象。
其次,克隆这个对象不需要使用构造函数。
然后,我们可能想要通父类指针或引用把指向的子类对象克隆出来,那么克隆可能会在父类和子类之间进行,并且可能是动态的,很明显通过父类的拷贝构造函数无法实现对子类对象的拷贝。
结构
在原型模式结构图中包含如下几个角色:
- Prototype(抽象原型类):它是声明克隆方法的接口,是所有具体原型类的公共父类,可以是抽象类也可以是接口,甚至还可以是具体实现类。
- ConcretePrototype(具体原型类):它实现在抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。
- Client(客户类):让一个原型对象克隆自身从而创建一个新的对象,在客户类中只需要直接实例化或通过工厂方法等方式创建一个原型对象,再通过调用该对象的克隆方法即可得到多个相同的对象。由于客户类针对抽象原型类Prototype编程,因此用户可以根据需要选择具体原型类,系统具有较好的可扩展性,增加或更换具体原型类都很方便。
⚠️注意:**浅克隆(浅复制)和深克隆(深复制)**之间的区别
| 特性 | 浅克隆 (Shallow Copy) | 深克隆 (Deep Copy) |
|---|---|---|
| 内存分配 | 不分配新内存,仅复制指针地址 | 分配新的内存空间存放数据副本 |
| 独立性 | 对象间共享底层数据,不独立 | 对象间完全独立,互不影响 |
| 默认性 | C++ 默认生成的拷贝构造函数 | 需要程序员手动编写代码实现 |
| 适用场景 | 对象不包含指针或动态分配的资源 | 对象包含指针、文件句柄或网络连接 |
| 崩溃风险 | 高(易出现悬挂指针或重复释放) | 低(管理得当则非常安全) |
实现
#include<iostream>usingnamespacestd;//PrototypeclassGermaSoldier{public:virtualGermaSoldier*clone()=0;virtualstringwhoAmI()=0;virtual~GermaSoldier(){}};//ConcretePrototypeclassSoldier66:publicGermaSoldier{public:GermaSoldier*clone()override{returnnewSoldier66(*this);}stringwhoAmI()override{returnstring("我是杰尔马66的超级士兵!!!");}};//ConcretePrototypeclassSoldier67:publicGermaSoldier{public:GermaSoldier*clone(){returnnewSoldier67(*this);}stringwhoAmI()override{returnstring("我是杰尔马67的超级士兵!!!");}};//Clientintmain(){GermaSoldier*obj=newSoldier66;GermaSoldier*soldier=obj->clone();cout<<soldier->whoAmI()<<endl;deletesoldier;deleteobj;obj=newSoldier67;soldier=obj->clone();cout<<soldier->whoAmI()<<endl;deletesoldier;deleteobj;}特点
主要优点
- 当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,通过复制一个已有实例可以提高新实例的创建效率。
- 扩展性较好,由于在原型模式中提供了抽象原型类,在客户端可以针对抽象原型类进行编程,将具体原型实现类写在配置文件中,增加或减少产品类对原有系统都没有任何影响。
- 原型模式提供了简化的创建结构,工厂方法模式常常需要有一个与产品类等级结构相同的工厂等级结构,而原型模式就不需要这样,原型模式中产品的复制是通过封装在原型类中的克隆方法实现的,无须专门的工厂类来创建产品。可以使用深克隆的方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,以便在需要的时候使用(如恢复到某一历史状态),可辅助实现撤销操作。
主要缺点
- 需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的内部,当对已有的类进行改造时,需要修改源代码,违背了“开闭原则”。
- 在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重的嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来可能会比较麻烦。
适用环境
- 创建新对象成本较大(如初始化需要占用较长的时间,占用太多的CPU资源或网络资源),新的对象可以通过原型模式对已有对象进行复制来获得,如果是相似对象,则可以对其成员变量稍作修改。
- 如果系统要保存对象的状态,而对象的状态变化很小,或者对象本身占用内存较少时,可以使用原型模式配合备忘录模式来实现。
- 需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少的几个组合状态,通过复制原型对象得到新实例可能比使用构造函数创建一个新实例更加方便。