我在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()
可能是我错了,但看起来这是两个不同的概念,偶然会有相似的名字。
我错过了什么吗?
答案 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}等等。