一、关于原型模式的解释:
原型模式是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类。
二、理解:
问题:如果你有一个对象, 并希望生成与其完全相同的一个复制品, 你该如何实现呢? 首先, 你必须新建一个属于相同类的对象。 然后, 你必须遍历原始对象的所有成员变量, 并将成员变量值复制到新对象中。
不错! 但有个小问题。 并非所有对象都能通过这种方式进行复制, 因为有些对象可能拥有私有成员变量, 它们在对象本身以外是不可见的。
直接复制还有另外一个问题。 因为你必须知道对象所属的类才能创建复制品, 所以代码必须依赖该类。 即使你可以接受额外的依赖性, 那还有另外一个问题: 有时你只知道对象所实现的接口, 而不知道其所属的具体类, 比如可向方法的某个参数传入实现了某个接口的任何对象。
解决方法:原型模式将克隆过程委派给被克隆的实际对象。 模式为所有支持克隆的对象声明了一个通用接口, 该接口让你能够克隆对象, 同时又无需将代码和对象所属类耦合。 通常情况下, 这样的接口中仅包含一个 克隆方法。
所有的类对 克隆方法的实现都非常相似。 该方法会创建一个当前类的对象, 然后将原始对象所有的成员变量值复制到新建的类中。 你甚至可以复制私有成员变量, 因为绝大部分编程语言都允许对象访问其同类对象的私有成员变量。
支持克隆的对象即为原型。 当你的对象有几十个成员变量和几百种类型时, 对其进行克隆甚至可以代替子类的构造。
所以原型模式的核心在于:实现类自身的clone方法,供外部使用,以达到快速和精准的复制。
参考:https://refactoringguru.cn/design-patterns/prototype
三、代码实现
先看一段实现类克隆自身的代码
#include <iostream>
using namespace std;
class A
{
private:
int a_value;
public:
A(){};
A(int value): a_value(value){};
~A(){};
A* clone(){return new A(*this);}; // 调用类隐藏的默认拷贝构造函数 A(const A&)
int getValue(){return a_value;};
};
int main(int argc, char **argv){
A *a1 = new A(10);
cout << a1 << " " << a1->getValue() << endl;
A *a2 = a1->clone();
cout << a2 << " " << a2->getValue() << endl;
return 0;
}
运行结果为:
0xee7228 10
0xee8240 10
可以看出,a2是独立于a1的对象,而且a2的私有变量a_value的数值与a1完全一致,a2是a1的完全克隆体,仅仅通过调用类对象的无参方法clone()实现了目的。
原型模型实现:现在假设有一个抽象基类A,克隆函数clone()为纯虚函数, 类B,和类C均继承自类A, 并分别实现自己的虚函数clone()。则有:
A *a1 = new B();
A *a2 = a1->clone(); // a1<=> a2
A *a3 = new C();
A *a4 = a3->clone(); // a3<=> a4