2009-11-12 32 views
1

看来我越谈论这个问题越好,我理解它。我认为我之前的问题没有传达我想要做的事。我对此表示歉意。我如何管理一组派生的,但不相关的类

在我的设计中,我有GameObjects,它本质上是一个聚合类,GameObject中的所有功能都是通过向它添加各种“功能”来实现的。 Feature是Feature类的子类,它具有自己的成员和函数。所有功能都可以接收消息

class Feature 
    { 
    public: 
     virtual void takeMessage(Message& message) = 0; 
    }; 

class VisualFeature : public Feature 
    { 
    public: 
     void takeMessage(Message& message); 
    private: 
     RenderContext m_renderer; 
    }; 

... Additional Features ... 

FeatureServers是负责协调各种功能的对象。 GameObjects可以订阅FeatureServers从他们那里收到消息,并且功能可以订阅GameObjects来处理它感兴趣的消息

因此,例如,在这个代码:

GameObject Square; 
VisualFeature* SquareSprite = new VisualFeature(); 
Square.subscribe(SquareSprite, "MESSAGE_RENDER"); 
Square.addFeature(SquareSprite); 
m_VisualFeatureServer.subscribe(Square, "MESSAGE_RENDER"); 

的VisualFeatureServer将追平消息以“MESSAGE_RENDER”这可能是这个样子

class Message 
    { 
    public: 
     std::string getID() {return m_id;} 
     bool isConsumed() {return m_consumed;} 
     void consume() {m_consumed = true;} 
    protected: 
     bool isConsumed; 
     std::string m_id; 
    } 

class Message_Render : public Message 
    { 
    public: 
     Message_Render() : m_id("MESSAGE_RENDER"), m_consumed(false) {} 
     RenderTarget& getRenderTarget() {return m_target;} 
    private: 
     RenderTarget& m_target; 
    }; 

当VisualFeatureServer发送Message_Render类的游戏对象坊它,然后将其转发给订阅任何FeatureComponents接收该特定消息。在这种情况下,VisualFeature类接收Message_Render消息。这里是我的问题所在,VisualFeature类将收到Message &,它可以通过它的ID识别Message_Render,我希望能够将其视为Message_Render而不是Message,如下所示:

void VisualFeature::takeMessage(Message& message) 
    { 
    //Here's the problem, I need a pattern to handle this elegantly 
    derivedMessage = convertMessageToDerivedType(message); 
    this->handleDerivedMessageType(derivedMessage); 
    } 

void VisualFeature::handleDerivedMessageType(Message_Render& message) 
    { 
    message.getRenderTarget().render(m_renderer); 
    message.consume(); 
    } 

有没有办法优雅地处理这个设计的takeMessage部分?

回答

1

另一个答案是编辑过于臃肿,所以我开始了一个新的。

你在做的receiveMessage()函数的铸造绝对是代码味道。

我认为你需要使用的组合:

的想法是,每个组件类型只会订阅自己类型的消息,因此只会收到针对它的消息。这应该消除铸造的需要。

作为示例,通知对象可以使用由消息ID索引的通知对象的向量。观察对象(派生组件类)可以订阅由其自己的消息ID索引的特定通知程序。

您认为这种设计模式会有所帮助吗?

+0

我认为它离我所想的更近,我能想到的唯一问题是VisualComponents可以接收各种消息。例如,移动消息(当玩家移动时发送的东西)会对很多组件感兴趣,可视化用于更新精灵位置,用于改变声音的3D位置的声音以及这些类型的东西。我同意铸造是一种代码味道。 – 2009-11-12 04:58:08

+0

更新了我的问题,我不认为我传达了我正在尝试做的正确事情。 – 2009-11-12 05:52:49

0

访客模式。如果我明白你在问什么。

虽然真的需要了解更多的上下文!

1

我不确定我是否真的了解你的问题,我认为你需要澄清你正在努力达到的目标。

虽然只是其他一些意见。

我不认为公共继承(如你已经实现)是在这里使用的最佳设计模式。具有公共继承的黄金法则是,只有在派生类类真正“是”基类类的对象时才应使用它。

一个使用C中的继承++的主要好处是实现多态性其中(例如),你有一个指针来Base对象列表,并调用这些对象的方法,他们被分派到相关VisualComponent和适当的对象方法。由于(用你的话来说)他们有“不相关的类接口”,你不会得到多态的任何好处。

听起来好像你真的从Base类继承来实现Mixin模式。

也许构图是更好的方法,在VisualComponentPhysicsComponent类中包含Base类(您将不得不重新命名)的副本。

然而,基于以下问题:

如果我只有一个引用或指针 到基地我有什么 设计方案,露出 VisualComponent或PhysicsComponent的接口?

是不是GameObject类(你在main()实例化)已经为你做这个?


编辑:

好吧,我想我现在好多了,这个问题已被编辑了解。

但我需要一些方法来动态地存储所有的 组件的游戏对象 ,但仍然能够使用 他们的单个接口。

唯一的办法我可以看到这个工作是通过创建一个Base方法virtual这是在每个派生类中重写并实现类特定的行为。 GameObject可以简单地存储指针的容器Base并调用将被派发到派生类的方法。

我也建议做Render()Move()任何非虚方法private,以便GameObject类只能访问公共(virtual)方法。有助于保持公共界面清洁。

我不确定这是否有帮助。


编辑2:

后在评论中进一步讨论,这听起来像factory patternabstract factory pattern是你所需要的。

+0

这个设计背后的想法是,我可以通过添加各种组件对象来专门化GameObjects,而无需为每个可能的组件组合创建特定的类,因为组件的数量可能会放大得多,然后只是视觉和物理。 – 2009-11-12 02:04:33

+0

我不确定您计划如何避免为每个可能的组件组合创建特定的类。如果他们每个独特的属性(成员数据)和行为(成员方法),我认为每个需要在一个单独的类。 – LeopardSkinPillBoxHat 2009-11-12 02:09:09

+0

我在答复中增加了一些内容 - 请让我知道这是否有帮助。 – LeopardSkinPillBoxHat 2009-11-12 02:14:55

0

看一看boost.signals

可以定义为每个消息类型的信号,并且允许特征添加槽(接收器)到它,这可以是任何名称的他们的成员函数,或者任何其他可调用事正确的签名。

相关问题