Question

It seems the more I talk about this problem the better I understand it. I think my previous question didn't convey what I am trying to do correctly. My apologies for that.

In my design I have GameObjects which are essentially an aggregation class, all functionality in a GameObject is implemented by adding various "Features" to it. A Feature is a Subclass of the Feature class that has it's own members and functions. All Features can receive Messages

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 are objects that are responsible for coordinating the various Features. GameObjects can subscribe to FeatureServers to receive messages from them, and Features can Subscribe to GameObjects to handle the messages it is interested in.

So for example in this code:

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

The VisualFeatureServer sends the message tied to "MESSAGE_RENDER" which may look something like this

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;
    };

When the VisualFeatureServer sends the Message_Render class to the Square GameObject it then forwards it to any FeatureComponents that are subscribed to receive that particular message. In this case the VisualFeature class receives the Message_Render message. Here is where my problem is, the VisualFeature class is going to receive a Message& that it can tell is a Message_Render by it's ID, I want to be able to treat it as a Message_Render rather then a Message like so:

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();
    }

Is there a way to elegantly deal with the takeMessage portion of this design?

Was it helpful?

Solution

The other answer was getting too bloated with edits, so I started a new one.

The casting you are doing in the receiveMessage() functions is definitely a code smell.

I think you need to use a combination of:

The idea is that each component type will only subscribe to messages of its own type, and will therefore only receive messages intended for it. This should eliminate the need for casting.

The notifying object could, as an example, use a vector of notifier objects indexed by the message ID. The observing object (the derived component class) could subscribe to the particular notifier indexed by its own message ID.

Do you think this design pattern would help?

OTHER TIPS

I'm not sure that I really understand your question, and I think you need to clarify what you are trying to achieve more.

Just a few other comments though.

I don't think public inheritance (as you have implemented) is the best design pattern to use here. The golden rule with public inheritance is that it should only be used if the derived class truly "is a" object of the base class.

One of the main benefits of using inheritance in C++ is to implement polymorphism where (for example) you have a list of pointers to Base objects and you invoke methods on those objects, and they are dispatched to the relevant VisualComponent and PhysicsComponent object methods as appropriate.

Since (in your words) they have "unrelated class interfaces", you won't get any of the benefits of polymorphism.

It sounds like you are really inheriting from the Base class to implement the Mixin pattern.

Maybe composition is the better approach, where you include a copy of the Base class (which you will have to rename) in the VisualComponent or PhysicsComponent class.

However, based on the following question:

If I only have a reference or pointer to Base what design options do I have to expose the interface of VisualComponent or PhysicsComponent?

Isn't the GameObject class (which you are instantiating in main()) already doing this for you?


Edit:

Okay, I think I understand better now that the question has been edited.

But I need some way to store all of the Components dynamically in the GameObject but still be able to use their individual interfaces.

The only easy way I can see this working is by creating a virtual method in Base which is overridden in each derived class and implements class specific behaviour. GameObject could simply store a container of Base pointers and invoke the virtual method(s) which will be dispatched to the derived classes.

I would also recommend making Render(), Move() and any non-virtual methods private so that the GameObject class can only access the public (virtual) methods. The helps keep the public interface clean.

I'm not sure if this helps.


Edit 2:

After further discussion in the comments, it sounds like the factory pattern or the abstract factory pattern is what you need.

Visitor Pattern. If I understand what you are asking.

Though really need to know more context!

Take a look at boost.signals

You can define a signal for each message type and allow features to add slots (receivers) to it, this may be their member-functions of any name, or any other callable things of a proper signature.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top