views:

113

answers:

4

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?

A: 

Visitor Pattern. If I understand what you are asking.

Though really need to know more context!

Keith Nicholas
+1  A: 

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.

LeopardSkinPillBoxHat
The idea behind this design was that I could specialize GameObjects by adding various Component objects without having to create a specific class for every possible combination of Component, since the amount of Components is likely to scale up much higher then just Visual and Physics.
VoDurden
I'm not sure how you plan to avoid creating a specific class for every possible combination of Component. If they each unique properties (member data) and behaviour (member methods) I would think that each would need to be in a separate class.
LeopardSkinPillBoxHat
I added some more to my answer - please let me know if this helps.
LeopardSkinPillBoxHat
I can see how the polymorphic approach would work I was hoping I could avoid that specific solution because of how different the interfaces could be between each Component, I was hoping there would be another solution. Something that lets me produce a class of VisualComponent from BaseComponent if say BaseComponent has an ID of 1 (Marking it as a VisualComponent)
VoDurden
Factory pattern is probably the best approach, or maybe abstract factory pattern:http://en.wikipedia.org/wiki/Abstract_factory_pattern
LeopardSkinPillBoxHat
Added some additional info to my question, I think I understand my problem a bit better now. Is the factory pattern applicable to my problem or is there something I'm missing?
VoDurden
+1  A: 

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?

LeopardSkinPillBoxHat
I think it's much closer to what I have in mind, the only problem I can think of is that VisualComponents can receive a variety of messages. For example a Move message (something sent when the player moves) would be interesting to a number of components, Visual for updating the sprite position, sound for changing the 3d location of the sound, those sorts of things. I agree that the casting is a code-smell.
VoDurden
Updated my question, I don't think I communicated what I was trying to do properly.
VoDurden
A: 

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.

maxim1000