API设计缺陷与工厂模式

时间:2013-07-20 00:36:00

标签: c++ api pointers factory

我正在使用工厂为物理引擎创建Shape个实例。每个形状的大小在构建时间之前是未知的,因此使用工厂代替堆栈存储器+克隆。然后将Shape提供给物理Scene以创建Body

// Sphere derives from Shape
Sphere *s = Scene.CreateSphere( radius );

// Construct a rigid body with a certain shape
Body *b = Scene.CreateBody( s );

问题:我希望每个Shape在任何给定时间只与一个Body相关联。我需要禁止用户这样做:

Body *b1 = scene.CreateBody( );
Body *b2 = scene.CreateBody( );
Shape *s = scene.CreateBox( 1.0f, 1.0f, 1.0f );
b1->AddShape( s );
b2->AddShape( s ); // bad

其他信息:最好避免对指针唯一性进行昂贵的性能检查,因为这里的性能非常重要。但是,在调试模式下,可以接受错误检查的性能命中。

能够与创建实体分开构造形状非常重要,因为多个形状可以是聚合刚体的一部分:

Body *b = Scene.CreateBody( );
b->AddShape( shapePtr1 );
b->AddShape( shapePtr2 );

Shape个实例也应该能够在运行时从一个Body转移到另一个;

Body *b1, b2; // initialized elsewhere
Shape *s;     // initialized elsewhere, is attached to b1
b1->RemoveShape( s );
b2->AddShape( s );

也许我应该采用不同的api设计?也许克隆可以某种方式使用?

2 个答案:

答案 0 :(得分:1)

首先,让所有Create*()函数都采用Body参数,作为依赖性反转的形式。

然后,您只能为单个Shape创建Body。如果您尝试在已有形状的Shape上创建Body,也可以断言或以其他方式输出错误。

您可以通过简单要求目标Shape尚未附加Body来支持移动Shape个对象。没有DetachShape,这将允许“悬空”形状,而只是MoveShapeToReleaseShape。或者,只需使用某种多样的智能指针,以确保正确清理“悬垂”形状,如果这是您的主要担心。

答案 1 :(得分:1)

Body::AddShape(...)设为私有,并删除带有Shape*参数的ctor。

void Body::AddSphere(float radius)
{
  AddShape(Scene.CreateSphere(radius));
}

void Body::transferShape(Shape *s, Body &B2)
{
  RemoveShape( s );
  B2.AddShape( s );
}

// Construct a rigid body with no Shapes (yet)
Body *b = Scene.CreateBody();

// Give it a Sphere
b->AddSphere(radius);

// Transfer it to another body:
Body *b2 = Scene.CreateBody();
Shape *s = b->GetShapePointerSomehow();
b->transferShape(s, *b2);

请注意,如果不将其从Shape移除,则无法将Body添加到Body。没有外部代码可以导致两个Bodies包含相同的Shape