【问题标题】:Patterns - Event Dispatcher without else if?模式 - 没有 else if 的事件调度器?
【发布时间】:2011-07-22 20:24:01
【问题描述】:

我正在为 Detours 库创建一个 Python 包装器。该工具的一个部分是调度程序,用于将所有挂钩的 API 调用发送到各种处理程序。

现在我的代码如下所示:

if event == 'CreateWindowExW':
    # do something
elif event == 'CreateProcessW':
    # do something
elif ...

这感觉很难看。是否有一种模式可以创建事件调度程序,而无需为每个 Windows API 函数创建 elif 分支?

【问题讨论】:

    标签: python design-patterns event-handling


    【解决方案1】:

    我没有在这个区域找到任何优雅的东西,所以我 wrote something 让你做:

    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
    

    还有一些其他的口味;文档是here,代码在github,包在pypi

    【讨论】:

      【解决方案2】:

      这样做的一个好方法是定义一个类,该类具有与相关 API 函数名称相同的方法,以及一个分派到正确方法的分派方法。例如:

      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()
      

      【讨论】:

        【解决方案3】:

        通常在这种情况下,如果您有预定义的操作列表,请使用地图,例如

        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"
        

        输出:

        CreateWindowExW
        UnkownAction Not Found
        

        所以使用地图你可以创建一个非常强大的调度器

        【讨论】:

          【解决方案4】:

          你可以使用 dispatch dict 方法。

          def handle_CreateWindowExW():
              print "CreateWindowExW"     
              #do something
          
          events = {
              "CreateWindowExW": handle_CreateWindowExW
          }
          
          events[event]()
          

          这样,您可以只添加事件而无需添加不同的if 语句。

          【讨论】:

            【解决方案5】:

            那些如果最终将不得不去某个地方。为什么不这样做:

            handler = get_handler(event)
            handler.process()
            

            get_handler 中,你有你的ifs,每个返回一个在process 方法中工作的对象。

            另一种方法是映射到可调用对象,如下所示:

            def react_to_create_window_exw():
               # do something with event here
               pass
            
            handlers = {
              "CreateWindowExW" : react_to_create_window_exw
            }
            

            你会这样使用它:

            handler = handlers[event]
            handler()
            

            这样你就不会使用任何 if/else 条件。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-12-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多