我越了解这个问题就越能理解。我认为我之前的问题没有传达我正在努力做的事情。我为此道歉。
在我的设计中,我有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来接收来自它们的消息,而Features可以订阅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类发送到Square GameObject时,它会将其转发给订阅接收该特定消息的任何FeatureComponents。在这种情况下,VisualFeature类接收Message_Render消息。这就是我的问题所在,VisualFeature类将接收一个Message&它可以告诉它是一个Message_Render它的ID,我希望能够将它视为Message_Render而不是像这样的消息:
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部分?
答案 0 :(得分:1)
我不确定我是否真的理解你的问题,我认为你需要澄清你想要达到的目标。
只是其他一些评论。
我不认为公共继承(如您所实现的)是这里使用的最佳设计模式。具有公共继承的黄金法则是,只有在派生的类真正“是基础类的对象时才应该使用它。
在C ++中使用继承的一个主要好处是实现多态,其中(例如)你有一个指向Base
对象的指针列表,你可以在这些对象上调用方法,并根据需要将它们发送到相关的VisualComponent
和PhysicsComponent
对象方法。
由于(用你的话说)他们有“不相关的类接口”,你将无法获得多态性的任何好处。
听起来你真的从Base
类继承来实现Mixin模式。
也许合成是更好的方法,您可以在Base
或VisualComponent
类中包含PhysicsComponent
类(您必须重命名)的副本。
但是,基于以下问题:
如果我只有引用或指针 根据我的设计选项 暴露界面 VisualComponent还是PhysicsComponent?
GameObject
类(你在main()
中实例化)是不是已经为你做了这个?
修改强>
好的,我想我现在已经对这个问题进行了编辑了解得更好。
但我需要一些方法来存储所有 动态组件中的组件 GameObject但仍然可以使用 他们各自的接口。
我能看到这个工作的唯一简单方法是在virtual
中创建一个Base
方法,该方法在每个派生类中被重写并实现特定于类的行为。 GameObject
可以简单地存储Base
指针的容器,并调用将被派遣到派生类的virtual
方法。
我还建议您制作Render()
,Move()
和任何非虚拟方法private
,以便GameObject
课程只能访问公众(virtual
) 方法。这有助于保持公共界面的清洁。
我不确定这是否有帮助。
编辑2:
在评论中进一步讨论之后,听起来factory pattern或abstract factory pattern就是您所需要的。
答案 1 :(得分:1)
另一个答案是编辑过于膨胀,所以我开始了一个新的。
你在receiveMessage()
函数中进行的转换绝对是代码味道。
我认为你需要结合使用:
这个想法是每个组件类型只订阅自己类型的消息,因此只接收用于它的消息。这样就不需要铸造了。
作为示例,通知对象可以使用由消息ID索引的通知对象的向量。观察对象(派生组件类)可以订阅由其自己的消息ID索引的特定通知程序。
您认为这种设计模式会有所帮助吗?
答案 2 :(得分:0)
访客模式。如果我明白你在问什么。
虽然真的需要了解更多背景信息!
答案 3 :(得分:0)
您可以为每种消息类型定义一个信号,并允许功能向其添加插槽(接收器),这可能是其任何名称的成员函数,或任何其他具有适当签名的可调用内容。