原型模式

Prototype Pattern

本文关键字:模式 原型      更新时间:2023-10-16

根据维基百科原型模式为:原型模式是软件开发中使用的一种创造性设计模式,当要创建的对象类型由原型实例确定时,该原型实例被克隆以生成新对象。此模式用于:

  1. 在客户端应用程序中避免对象创建者的子类,就像抽象工厂模式一样。

  2. 避免以标准方式(例如,使用new关键字)创建新对象的固有成本,因为对于给定的应用程序来说,这是非常昂贵的。


我在C++中看到了这种模式的某些演示代码,所有这些代码都使用了复制构造函数。有人能解释第二点是如何应用的吗(在一般情况下以及在C++的上下文中),因为我们无论如何都在克隆函数中使用复制构造函数。如果它可以在没有复制构造函数的情况下完成,那么一个示例代码片段将非常好。

您可以在没有动态分配的情况下进行复制。例如,这里有一个只在本地范围内进行的克隆:

Foo prototype;
void local()
{
    Foo x = prototype; // first copy
    x.mutate();
    Foo y = x;         // another copy
}

从未使用过动态分配。

的确,return new Foo(*this);进行复制,但更重要的是该对象是动态分配的这是你的文章所暗示的成本。

在我用Java制作的一个游戏中,我遇到了一个非常符合原型模式要求的有趣情况。你看,我有一个动画对象,它存储了一个要翻转的图像容器,以及一些其他数据,这些数据跟踪了上一帧渲染后的时间,它在哪个帧上,动画是否正在运行,等等

我发现多个角色使用同一个动画对象会造成问题。如果两个角色共享一个动画,他们会在相互冲突的时间打开和关闭动画。我会让男人用走路的动画站着不动,或者用站着的动画移动。动画对象的创建既昂贵又耗时,比如创建精灵、设置它们将显示的时间弹药数、创建图像的间隔队列等。

相反,我将Animation对象作为原型对象。如果一个动画克隆自己,它会与所有其他动画共享原始帧集合,因为这些帧是不可变的,但构建起来也很昂贵。相反,新对象将共享这个不可变的基础,但有自己的信息,即绘制哪一帧以及何时绘制。

把它想象成一台投影仪。当它被克隆时,新的投影仪可能会有自己的信息,比如它是否在运行,它在哪个帧上,等等,但它可能使用的是与原始投影仪使用的相同的胶片。他们之所以不绊倒对方,是因为这部电影是永恒的。(创建成本高昂)

老实说,以这种方式使用原型是实现轻量级模式的好方法。共享创建成本高昂的对象的对象。如果你"克隆"它们,它们会被实例化为新的瞬态,但仍然与它的创建者共享那些昂贵的基本对象。

为内部不使用动态内存的对象调用复制构造函数要比通过new在动态内存中执行任何分配快得多。因为动态内存中的分配是一种系统调用。