C++设计模式专栏:http://t.csdnimg.cn/8Ulj3
目录
1.概述
原型模式(Prototype Pattern)顾名思义通过一个接口实现快速创建对象,主要解决的问题就是创建重复对象,而这部分对象内容本身比较复杂,生成过程可能从库或者RPC接口中获取数据的耗时较长,因此采用克隆的方式节省时间。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式之一。
原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。
2.结构
原型模式的UML类图如下所示:
角色定义:
**Prototype(原型类):**声明一个克隆自身的接口,用来约束想要克隆自己的类,要求它们都要实现这里定义的克隆方法。
**ConcretePrototype(具体原型类):**实现 Prototype接口的类,这些类真正实现了克隆自身的功能。
**Client(客户类):**使用原型的客户端,首先要获取到原型实例对象,然后通过原型实例克隆自身来创建新的对象实例。
3.简单实现示例
在C++中,原型模式可以通过复制构造函数和克隆方法来实现。复制构造函数用于创建一个与现有对象具有相同状态的新对象,而克隆方法则通常是一个虚函数,用于在子类中实现自定义的复制逻辑。
以下是一个简单的C++原型模式的示例:
cpp
#include <iostream>
#include <memory>
class Prototype {
public:
virtual std::unique_ptr<Prototype> clone() const = 0;
virtual void display() const = 0;
};
class ConcretePrototype : public Prototype {
private:
int value;
public:
ConcretePrototype(int val) : value(val) {}
std::unique_ptr<Prototype> clone() const override {
return std::make_unique<ConcretePrototype>(value);
}
void display() const override {
std::cout << "ConcretePrototype: " << value << std::endl;
}
};
int main() {
std::unique_ptr<Prototype> prototype = std::make_unique<ConcretePrototype>(10);
prototype->display(); // 输出: ConcretePrototype: 10
std::unique_ptr<Prototype> clonedPrototype = prototype->clone();
clonedPrototype->display(); // 输出: ConcretePrototype: 10
return 0;
}
在这个示例中,我们定义了一个Prototype
基类,它包含两个纯虚函数:clone()
和display()
。ConcretePrototype
类继承自Prototype
类,并实现了这两个函数。clone()
函数返回一个指向新创建的ConcretePrototype
对象的unique_ptr
,该对象与原始对象具有相同的value
。display()
函数则用于显示对象的值。
在main()
函数中,我们首先创建了一个ConcretePrototype
对象,并调用其display()
函数来显示其值。然后,我们使用clone()
函数创建了一个新的ConcretePrototype
对象,并再次调用其display()
函数来显示其值。由于两个对象具有相同的value
,因此它们的输出应该是相同的。
注意,在这个示例中,我们使用std::unique_ptr
来管理对象的生命周期,以确保在不再需要对象时能够正确释放其内存。这是一种良好的C++编程实践,可以帮助避免内存泄漏和其他相关问题。
4.使用场景
原型模式的使用场景广泛且多样,特别适用于需要避免大量实例化或频繁创建具有相似属性的对象的情况。以下是原型模式的一些主要使用场景:
- 资源优化场景:当类初始化需要消耗大量资源,包括数据、硬件资源等时,使用原型模式可以避免这些消耗。通过复制一个已有的对象来创建新对象,而不是每次都重新进行初始化,可以显著提高性能。
- 创建大量相似对象:当系统需要创建大量相似对象时,原型模式可以显著提高对象的创建效率。通过复制一个原型对象来创建新对象,可以避免重复的初始化过程。
- 对象创建成本较高:如果创建对象的过程比较复杂或耗时较长,使用原型模式可以避免这种昂贵的创建过程。通过复制现有对象的属性和方法,可以快速生成新的对象实例。
- 对象的修改频繁:如果对象的属性经常变化,并且每次变化都需要创建新的对象,原型模式可以通过复制原型对象来创建新对象并修改其属性,从而避免每次都重新创建对象。
- 隐藏对象的创建细节:当创建对象的细节比较复杂,不希望客户端直接与创建对象的过程耦合时,原型模式可以隐藏这些细节。客户端只需要通过复制一个已有对象来创建新对象,而无需知道创建的细节。
- 性能和安全要求的场景:在性能要求严格或安全性要求高的场景中,原型模式可以提供更高效、安全的对象创建方式。
需要注意的是,原型模式在实际项目中很少单独出现,通常会与其他设计模式如工厂方法模式结合使用。此外,在使用原型模式时,还需要注意深拷贝和浅拷贝的区别,以及它们对对象状态的影响。深拷贝会创建对象的一个完全独立的副本,而浅拷贝则可能只是复制了对象的引用,而不是实际的对象数据。因此,在选择使用原型模式时,需要根据具体的需求和场景来选择合适的拷贝方式。
5.总结
原型模式的优点:
- 便于通过克隆方式创建复杂对象、也可以避免重复做初始化操作.不需要与类中所属的其他类耦合等。
原型模式的缺点:
- 如果对象中包括了循环引用的克隆,以及类中深度使用对象的克隆,都会使此模式变得异常麻烦。
综上所述,原型设计模式在特定场景下具有显著的优势,但也需要注意其潜在的缺点和限制。在选择是否使用原型设计模式时,需要根据具体的应用场景和需求进行权衡。