English 中文(简体)
How can I manage a group of derived but otherwise Unrelated Classes
原标题:

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?

最佳回答

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?

问题回答

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.





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签