也叫克隆模式
意图
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
适用性
克隆模式应用于下列情况:
- 一个系统要独立于它的产品的创建、构成和表示时。
- 当要实例化的类是在运行时刻指定时,例如:通过动态装载。
- 为了避免创建一个与产品类层次平行的工厂类层次时。
- 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
(其实我都没想到 C++ 用原型模式的必要性,为什么不直接用 decltype + 拷贝构造函数来创建对应的对象呢)
结构
Prototype:声明一个克隆自身的接口。
ConcretePrototype:实现一个克隆自身的操作。
Client:让一个原型克隆自身从而创建一个新的对象。
细则
java 好像可以通过 clone 来提高创建对象的效率,不过 C++ 里除了封装性好像也没什么特别的。
Prototype 的主要缺陷是每一个 Prototype 子类都必须实现 Clone 操作,这可能很困难。例如,当所考虑的类已经存在时就难以新增 clone 操作。当内部包括一些不支持拷贝或有循环引用的对象时,实现克隆可能也会很困难。
代码示例
#include <iostream>
class Base
{
public:
Base() = default;
virtual ~Base() = default;
Base(const Base& other) {
if (&other == this)
return;
num = other.num;
}
void setNum(int n) {
num = n;
}
virtual void hello() {
std::cout << "Base hello " << num << std::endl;
}
//子类必须实现clone接口
virtual Base* clone() {
return new Base(*this);
}
protected:
int num{ 0 };
};
class Sub : public Base
{
public:
Sub() = default;
Sub(const Sub& other) {
if (&other == this)
return;
num = other.num;
}
void hello() override {
std::cout << "Sub hello " << num << std::endl;
}
Base* clone() override {
return new Sub(*this);
}
};
int main()
{
Base* a = new Sub;
a->setNum(11);
a->hello();
decltype(a) b(a);
b->hello();
Base* c = a->clone();
c->hello();
system("pause");
return 0;
}
相关模式
- Abstract Factory 可以和 Prototype 结合使用。
- 大量使用 Composite 和 Decorator 模式的设计通常也可以从 Prototype 模式处获益。
参照
书籍:GOF《设计模式:可复用面向对象软件的基础》
视频:李建忠设计模式(版权问题,自行搜索)