Patterns - Event Dispatcher without else if?
I'm creating a Python wrapper for the Detours开发者_如何转开发 library. One piece of the tool is a dispatcher to send all of the hooked API calls to various handlers.
Right now my code looks like this:
if event == 'CreateWindowExW':
# do something
elif event == 'CreateProcessW':
# do something
elif ...
This feels ugly. Is there a pattern to create an event dispatcher without my having to create an elif
branch for each Windows API function?
One nice way to do this is to define a class which has methods equating to the relevant API function names, plus a dispatch method which dispatches to the correct method. For example:
class ApiDispatcher(object):
def handle_CreateWindowExW(self):
# do whatever
def handle_CreateProcessW(self):
# do this one
def dispatch(self, event):
method = getattr(self, 'handle_%s' % event)
method()
Those if's will eventually have to go somewhere. Why not do it like this:
handler = get_handler(event)
handler.process()
and in the get_handler
you'd have your ifs, each returning an object which does its work in the process
method.
An alternative would be a map to callables, like this:
def react_to_create_window_exw():
# do something with event here
pass
handlers = {
"CreateWindowExW" : react_to_create_window_exw
}
and you would use it like this:
handler = handlers[event]
handler()
This way you would not use any if/else conditions.
You can use the dispatch dict method.
def handle_CreateWindowExW():
print "CreateWindowExW"
#do something
events = {
"CreateWindowExW": handle_CreateWindowExW
}
events[event]()
This way, you can just add events without having to add different if
statements.
Usually in such cases when you have a predefined list of actions to take, use a map e.g.
def CreateWindowExW():
print 'CreateWindowExW'
def CreateProcessW():
print 'CreateProcessW'
action_map = {
'CreateWindowExW': CreateWindowExW,
'CreateProcessW': CreateProcessW
}
for action in ['CreateWindowExW', 'UnkownAction']:
try:
action_map[action]()
except KeyError:
print action, "Not Found"
Output:
CreateWindowExW
UnkownAction Not Found
so using a map you can create a very powerful dispatcher
I didn't find anything that was as graceful as it could be in this area, so I wrote something that let's you do:
from switcheroo import Switch, default
switch = Switch({
'foo': lambda x: x+1,
default: lambda x: x-1,
})
>>> switch['foo'](1)
2
>>> switch['bar'](1)
0
There are some other flavours; docs are here, code is on github, package is on pypi.
精彩评论