最好的方式来处理象,不能实例?
-
18-09-2019 - |
题
我猜我已经问了几个相似的问题之前,我打周围的灌木丛中。我认为这是真正的问题,我不能躺着休息。
我处理一个 第三方图书馆, 有一个对象,不可能创建自己, b2Body
.的 b2World
已 化它.我不喜欢这个设计图案很多;我认为的 b2Body
应该能够独立存在的世界,然后被添加到全世界,当需要。无论如何,我的包裹 b2Body
与我自己的类类 Body
, 因为我需要添加一些额外的东西给它无论如何。同样,我有一个 World
包装。现在我想我有3个选择:
- 已
Body
's需要构造一个指向World
所以它可以完全实例(电话b2World::CreateBody
里面的某个地方)--即有一个构造像Body *b = new Body(world_ptr)
- 通
Body
到一些World::CreateBody
方喜欢怎样的图书馆已经不--即Body *b = world.CreateBody(params);
- 重复的所有数据
b2Body
这样就可以使用它,但是你想要的,然后添加到全世界,它将开了'使用b2Body
数据--即Body b
和之后world.addBody(b)
.
(1)和(2)的意思是,你不能有一个 Body
没有一个 World
, 我可能不需要,但它可能是不错的选择[这样,我可以使用它作为模板,用于其他目的而这样的].不知道什么其他的优点和缺点。(3)似乎更好,但这是一个更多的工作来实现,这意味着我必须重复的大多数数据已经包含在 b2Body
.
你有什么想法?我 CW
这只所以没有一个苦恼。
我仍然不能躺在这休息。这是什么每个选择会是这样的:
备选案文1: (什么我更喜欢)
World w;
Body b;
Fixture f;
b.addFixture(f);
w.addBody(b);
备选2: (在中间的某个地方)
World w;
Body b(w);
Fixture f(b);
备选案文3: (怎么Box2D它不会)
World *w = new World;
Body *b = w->CreateBody(args);
Fixture *f = b->CreateFixture(args);
备选方案2和3不是那么不同,但是它改变谁拥有控制创造的对象。
我将如何实际执行备选办法3有关系吗? World::CreateBody()
已经呼叫 b2World::CreateBody(args)
这电话 b2Body::b2Body()
和返回 b2Body
但从来不打电话 Body::Body(args)
这是一个问题。的 b2Body
会得到充分的初始化,但我的包皮已经没有地方做的事情...更具体地说,我怎么会写 World::CreateBody(const BodyDef &bd)
?假设BodyDef继承b2BodyDef、身体从b2Body,世界从b2World,等等。
解决方案
我想,如果你要用一个第三方图书馆,你应该只争取它的设计如果你有一个更好的原因 哦,我不喜欢这个设计图太多.你的图书馆拥有一种方式做事的—很显然,通过使用工厂的目的和战斗将会增加你的代码复杂性,可能大大。
其他提示
听起来像b2World对象是工厂b2Body,因此提交人已经决定,一个b2Body已经没有意义没有它的世界。
我的第一反应会是这个接口,这样的生活。有你的世界,象是一个工厂于你的身体。所以这是接近的方法(1)除了你没有一个公共构造,世界对象具有makeBody()方法。
你认为尸体没有世界意义?如果是这样,也许你的发现是,一些集体方法可能是有用的,没有一个世界,我不清楚你如何实现它们-他们显然不能够实施通过b2Body,因为他不可能存在没有一个b2World.这样一种可能性是,你有一套配置的信息
class Body {
int howBig;
String name;
Flavour flavour;
// and getter/setters
}
现在这些(或在东bgetters)清楚可能是有意义的有或没有的世界。
考虑到这一点,我想你可能会发现你的真正有两个"国家"的身体,一个当它是不相关联的世界,一个时就是如此。和实际的能力 不同的.因此,你实际上有两个接口。
因此,有一个IndependentBody类和一体类。世界工厂的方法可能有一个签名
World {
Body makeBody(IndependentBody);
}
以下你的链接时,我看到 createBody
不返回b2Body,但一个 指针 一:
b2Body* b2World::CreateBody ( const b2BodyDef* def );
这可能是因为b2World
管理b2Body生(即, 删除和存储它使用当B2World超出范围/本身就是删除),或
因为B2Wsorld需要保持针对b2Bodies, 例如 迭代过他们为完成某些B2World的功能。
我还注意到所有的需要(其他比 b2World
)创建一个 b2Body
是指向 b2BodyDef
.
所以如果你想要一个b2Body,没有连接到一个b2World,但可以在后来的一些被附加于一个,你为什么不能通过围绕b2BodyDefs,或针对他们?
我 可能会 创建一个薄包装为一个b2BodyDef, 例如,:
class b2BodyDefWrapper {
public const b2BodyDef& b2bodyDef;
public b2BodyDefWrapper( const b2BodyDef& bodydef ) : b2bodyDef(bodydef) {}
public const b2Body* reifyOn( b2World& world) const {
return world.CreateBody( b2bodyDef ) ;
}
}
注意,我可以将这种b2BodyDefWrapper多的世界,或以同样的世界上超过一次。
现在它可能是你可以做的事情到b2Body你不能做到一b2BodyDef,以便通过周围(可能包裹的)b2BodyDefs不会满足您的目的。在这种情况下,我可能使用该指令模式"附加"一个列表中的职能 b2BodyDefWrapper
, 那将是"重播"在每个抛b2Body:
class b2BodyDefWrapper {
private std::vector<Command&> commandStack;
public const b2BodyDef& b2bodyDef;
public b2BodyDefWrapper( const b2BodyDef& bodydef ) : b2bodyDef(bodydef) {}
public const b2Body* reify( b2World& world) const {
b2body* ret = world.CreateBody( &b2bodyDef ) ;
for (int i=0; i< commandStack.size(); i++) {
v[i].applyTo( ret ) ;
}
return ret;
}
public void addCommand( const Command& command ) {
commandStack.push_back( command );
}
}
哪里 Command
是一个抽象的基类函,像这样:
class Command {
virtual ~Command() {}
virtual void applyTo( b2Body* body ) = 0 ;
}
与具体的子类:
class ApplyForce : public Command {
private const b2Vec2& force;
private const b2Vec2& point;
ApplyForce(const b2Vec2& f, const b2Vec2& p) : force(f), point(p) {}
virtual void applyTo( b2Body* body ) {
body->ApplyForce( force, point ) ;
}
}
然后我可以用我的包装这样的:
extern b2BodyDef& makeb2BodyDef();
b2BodyDefWrapper w( makeb2BodyDef() ) ;
ApplyForce a( ..., ... );
w.addCommand( a ) ;
...
b2World myworld;
b2World hisWorld;
w.reifyOn( myWorld ) ;
w.reifyOn( hisWorld) ;
注意,我已经离开了一些细节,主要是关于物体的所有权和存储管理,并要求删除关于CommandStacks;我也没有遵循规则的三个在我的草图的课程。你可以填补这些你喜欢的。
我也有留出任何规定调用,从命令,b2Body功能返回的其他无效和回这些价值观;你或许可以涵盖这种(如果您需要)通过具有ApplyTo返回联盟的某种。
更根本的是,我没有涵盖如何一个具体的命令可以提供其返回值(如果有)到另一个具体的命令。一个完整的解决方案将有不一矢量的命令,但一个 n元树他们,那里的儿童的命令,首先应用,以及他们的返回值(如果有的话)是提供给他们的父的命令。无论你 需要 这种复杂性是一个问题,我显然不能回答。(我已经给出一个相当详细的回答,认为我是既没有得到支付这个,我也不是越来越声誉点,由于你的社会Wiki就这个问题。)
我同意,你不该战斗的设计的一个第3方图书馆,你使用。走这样的路径可能会导致大量的未来的问题。
通过寻找"下面"和创造包装,你可能被锁定的行为的第3党库的方式在当前实施的行为。
会发生什么,如果一个未来的版本的API保持不变,但基本义改变?
突然,一切都是打破从一点看你的包装。
只是我的0.02.
其中一个原因,box2D使用bodyDef对象建造b2Body目的是使得可以重新使用的清晰度,以创建多个机构。代码,如:
b2BodyDef myDef;
// fill out def
for (int i=0; i < 100; ++i) {
for (int j=0; j < 100; ++j) {
myDef.x = i;
myDef.y = j
b2Body* body = world.CreateBody(myDef)
}
}
是一个非常有效和紧凑的方式创建多的对象,用相同的特性。它不必在同样的循环,你可以保持清周围的物体作为元数据,并创建机构从它们的需要。
不要打它,因为它是有原因的。