2009-09-29 238 views
22

我一直在寻找在Python ... 一个命令模式实现(据Wikipedia总指挥部模式和指挥调度模式

命令模式是设计 模式,其中对象是用来代表 并在 封装调用一个方法所需要的所有信息 稍后的时间。

我发现的唯一的事情是指挥调度pattern

class Dispatcher: 

    def do_get(self): ... 

    def do_put(self): ... 

    def error(self): ... 

    def dispatch(self, command): 
     mname = 'do_' + command 
     if hasattr(self, mname): 
      method = getattr(self, mname) 
      method() 
     else: 
      self.error() 

可能是我错了,但是看起来这是两个不同的概念,它不小心有相似的名称。

我错过了什么?

回答

54

最简单的命令模式已经构建成Python,只需使用一个可调用:

def greet(who): 
    print "Hello %s" % who 

greet_command = lambda: greet("World") 
# pass the callable around, and invoke it later 
greet_command() 

作为一个面向对象的设计模式命令模式更有意义,如果你的命令需要能够做的不仅仅是被调用。常用的用例是当你需要能够撤销/重做你的动作时。然后一个命令类是将前进和后退动作耦合在一起的好方法。例如:

class MoveFileCommand(object): 
    def __init__(self, src, dest): 
     self.src = src 
     self.dest = dest 
     os.rename(self.src, self.dest) 
    def undo(self): 
     os.rename(self.dest, self.src) 

undo_stack = [] 
undo_stack.append(MoveFileCommand('foo.txt', 'bar.txt')) 
undo_stack.append(MoveFileCommand('bar.txt', 'baz.txt')) 
# foo.txt is now renamed to baz.txt 
undo_stack.pop().undo() # Now it's bar.txt 
undo_stack.pop().undo() # and back to foo.txt 
+0

感谢您的撤销示例:它很小(很容易理解),并很好地说明了这个概念。 – 2010-11-22 16:21:29

+0

+1清晰简单的例子。 – hiwaylon 2012-03-05 12:47:20

2

是的,你错过了一些东西:只有在没有函数指针的语言(或函数作为第一类对象)时才需要命令模式,比如Java。在函数作为对象的语言中,您可以使用函数本身;不需要单独的命令对象(然后应该有一个“doit”方法)。在这个例子中你可以引用,getattr()调用为你提供了“命令对象”(即绑定方法)。在“调用”(即调用)命令对象之后添加括号。

+8

我认为这是一个坏主意,假定命令模式不是“必要的”,只是因为函数是第一类对象。命令模式不仅仅是传递可调参数,它是关于创建强大的执行模型描述。能够在一段时间内持续部分应用的命令,然后回忆该命令并在稍后完成时也很有用。在python中持久化函数是棘手的,坚持用户定义的命令并不那么简单。 – apiguy 2010-10-15 13:12:08

3

做了一些搜索,发现这一点。它似乎在做封装行动的工作。

def demo(a,b,c): 
    print 'a:',a 
    print 'b:',b 
    print 'c:',c 

class Command: 
    def __init__(self, cmd, *args): 
     self._cmd=cmd 
     self._args=args 

    def __call__(self, *args): 
     return apply(self._cmd, self._args+args) 


cmd=Command(dir,__builtins__) 
print cmd() 

cmd=Command(demo,1,2) 
cmd(3) 
+0

'apply'被认为是“非必要的”:https://docs.python.org/2/library/functions。html#非必要内置funcs – Florian 2015-09-11 21:36:23

2

如果我记错的四人帮,Command模式是关于像“文件 - 保存”命令,如“SVN提交”,这是你的代码是什么好不是命令。

马丁表明Command模式是不需要的,因为用作第一类对象代替它,但Command模式不仅仅是doit()更丰富,具有,例如,也undo()is_enabled()

+1

我相信撤消的整合是令人困惑的问题。我所看到的命令模式的每个描述都提到可以撤消,但实际的代码只有Execute()方法的接口(不支持撤销)。所以我认为命令模式的“丰富性”实际上混合了独立用例,其中主要用例只是关于*参数较少的*回调操作。 – 2009-09-29 19:52:37