Python中的常规命令模式和命令调度模式

时间:2009-09-29 19:23:23

标签: python design-patterns oop

我在Python中寻找 Command 模式实现... (根据Wikipedia

  

命令模式是一种设计   使用对象的模式   代表并封装所有的   调用方法所需的信息   以后。

我发现的唯一一件事是Command Dispatch 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()

可能是我错了,但看起来这是两个不同的概念,偶然会有相似的名字。

我错过了什么吗?

4 个答案:

答案 0 :(得分:56)

最简单的命令模式已经内置到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

答案 1 :(得分:4)

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

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)

答案 2 :(得分:2)

是的,你确实错过了一些东西:只有在没有函数指针(或函数作为第一类对象)的语言中才需要命令模式,例如Java。在具有函数作为对象的语言中,您可以使用函数本身;不需要单独的命令对象(然后应该有一个“doit”方法)。

在这个例子中你可以引用,getattr()调用给你“命令对象”(即绑定方法);在“调用”(即调用)命令对象后添加括号。

答案 3 :(得分:2)

如果我正确地回想起四人一组,那么命令模式是关于“文件 - 保存”之类的命令,而不是像“svn commit”这样的命令,这是你的代码所适用的。

Martin建议不需要Command模式,因为作为第一类对象的函数取而代之,但Command模式比doit()更丰富,例如undo(),{{1}等等。