Quote:Original post by kloffy
I'm also interested in the instance set-up with appropriate references, do you have an example of how that would look like?
That's nothing mysterious.
Using your example of a the pausing button, it may look like this:
// c'tor gets all collaborators needed, and stores them in member fieldsCPauseButton::CPauseButton(Game& gameInstance): _gameInstance(gameInstance) { }// typical instantiationnew CPauseButton(gameInstance);
Simply supply all dependent objects at initialization time. At initialization you have to know the _exact_ type, so it is not hard to supply specific parameter.
However, the above example isn't good since it uses a special purpose button for a single acton, and that's not good as already seen ;)
So, here is a Listener/Mediator example:
class Button: public GUIObject {public: // listener class Listener { public: virtual void noticeAction(Button* sender) =0; };public: // c'tors Button(Listener* listener) : _listener(listener) { }public: // action void onPress() { if(_listener) { _listener->noticeAction(this); } }};class Game: public Button::Listener {public: // c'tors Game() { objects["Pause"] = new Button(this); objects["Resume"] = new Button(this); }public: // listeners void noticeAction(Button* sender) { if(sender==objects["Pause"]) { this->pause(); } else if(sender==objects["Resume"]) { this->resume(); } else if(...) { // doing something appropriate } else { // error: unknown sender; e.g. throw exception } }};
Here the Game class's noticeAction routine is implemented as mediator, what means that the routine first checks which of all known possible senders is the one that actually has invoked the routine (a kind of dispatching). Then the routine performs the appropriate action.
Similarly a, say, slider widget could be implemented, like here:
class Slider: public GUIObject {public: // listener class Listener { public: virtual void noticeChange(Slider* sender) =0; };public: // c'tors Slider(Listener* listener) : _listener(listener) { }public: // action void onDrag() { if(_listener) { _listener->noticeChange(this); } } float getCurrentFraction() const { // returning fraction between 0 and 1 as slider's knob position }};
To make life easier (and avoid multiple inheritance) one could move the Listener interface into GUIObject, so that one single routine is used for every and all action. The state could simply be extracted from the overhanded sender. (Okay, one has to do some casting then.)
Btw: If you're intersted in such stuff, I recommend you to get at least one book about software design patterns. E.g. the book of the "Gang of Four" (GoF) is it worth.
[Edited by - haegarr on April 5, 2006 12:40:34 PM]