麻烦搞清楚对象组成

时间:2013-09-22 02:36:16

标签: architecture go object-composition

我目前正在使用go来实现一个游戏服务器,因为它具有很棒的并发原语。这一切都是轻而易举的,并且工作非常可靠。我主要来自Java背景,但我忘记了Java的类型层次结构。我需要有一组游戏对象,它们共享类似的数据结构,如位置,速度等,但它们在更新方法或特殊字段中可能都有不同的行为以允许不同的功能。最初我有一个包含所有共享数据的结构,每个自定义类型都会嵌入该结构。麻烦在于使用数据结构进行组织。我使用四叉树来向客户通知附近对象的状态。这样我就可以将树指针传递给每个游戏对象的嵌入式结构,一切正常。

这个问题是我查询四叉树后无法访问包含类型。例如,

type GameObject struct {
    Position Point
    Velocity Point
    ID int32
}

type Client struct {
    GameObject
    conn net.Conn
    // other fields
}

现在,如果我想更新附近的玩家有关对象的状态,我查询四叉树,但现在有办法确定GameObject是否实际上是一个客户端,并且没有办法访问它的连接以发送数据包

从Java开始,我习惯于创建一个基类并将其子类化为Client等。然后我可以使用instanceof来确定哪些需要特殊处理并相应地转换它们来访问自定义功能。我想我可以做类似以下的事情:

type GameObject interface {
    Position() Point
    Velocity() Point
    ID() int32
}

type Client struct {
    pos Point
    vel Point
    id int32
    conn net.Conn
    // other fields
}

func (c *Client) Position() Point {
    return c.pos
}

func (c *Client) Velocity() Point {
    return c.vel
}

func (c *Client) ID() int32 {
    return c.id
}

使用这种方法,我可以使用类型断言来隔离客户端,但这会导致许多重复的代码用于实现其他游戏对象。我认为有一种更惯用的方式来做这样的事情,我很感激我能得到的任何帮助。如果这是顺便说一句,也许有人可以帮助我理解这种设计背后的原因。

1 个答案:

答案 0 :(得分:0)

如果不了解问题和你的约束,很难回答这个问题,但这里有三个想法。

首先,也许您可​​以在四叉树中存储复合类型,而不仅仅是GameObject指针。

type QuadTreeEntry struct {
   GameOb *GameObject
   Entity interface{}
}

“实体”将是*客户端,以及您的四叉树中的任何其他内容。

其次,您可能会考虑是否需要四叉树中的所有GameObject。也许这会更好?

type QuadTreeEntry struct {
    Position Point
    Entity interface{}
}

这具有移除间接以获得QuadTree代码中的位置的良好效果,并且由于其不与原始实体共享位置数据而更难以意外地使QuadTree无效。

第三,如果效率不是很重要,你可以这样做:

type GameObjectGetter interface {
    GetGameObject() *GameObject
}

func (c *Client) GetGameObject() *GameObject {
    return &c.GameObject
}

因此,四叉树中的所有内容都是GameObjectGetter。