Reputation: 560
Using C++ & MFC I've created a class which makes it easier to add drag/drop functionality to a CWnd
object. There is nothing special about it really. Currently it is used like so:
CWnd
objectCWnd
It is a bit cumbersome having to create a class member variable for each listener, and I was just wondering which design pattern would be more suitable for this. I only need the member objects so that I can delete
them at the end. I thought I could just use an array to store them in and it would simplify it a bit, but I also thought there might be a better way where you can just call a static function similar to DropListener::RegisterListener(CWnd* wnd, CString& extension, void(*callback) callback)
and it handles all of the creating / registering / deleting for you.
Upvotes: 1
Views: 5140
Reputation: 3731
I'm not familiar with MFC but from an OO point of view your design can be improved.
First identify what aspects of your requirements are most likely to change and then identify what the interfaces needed to isolate those changes are:
Changes:
Interfaces:
So you need an Event
interface, a Callback
interface, and a Notifier
interface.
In C++ there is a handy thing called std::function<T>
where T
is any callable type (a pointer to a function, a functor
, a lambda
). So you should probably use that for encapsulating your callbacks to give your user more freedom.
Then how may event types do you want to support? This will tell you whether you need to support different Event
objects as well as how your registration will look:
// For example if you support just `Drop` events:
void addDropListener(std::function<T> callback);
// If you support many events:
void addListener(Event::Type evType, std::function<T> callback);
Once you have answered that you need to decide what a "callback" looks like (T
in the above examples). This could return a value (if you want success verification) or throw a particular exception type (make sure to document the contract). Then ask if you want a copy of the event that was fired (usually you would). Assuming you are happy to only be notified of errors via exceptions then you can typedef the expected std::function like this:
typedef std::function<void (const Event&)> EventCallback;
I recommend then that your Notifier
implementer use a std::vector<EventCallback>
or std::map<Event::Type, std:vector<EventCallback>
. The first one is useful if you want to only support one event type or to call all listeners for all events. The second is handy when you want to only notify listeners of certain types of event.
In any case if you are finding that you need to change your class code to accommodate minor changes to behaviour then you need some refactoring.
Hope that helped. :)
Upvotes: 5