Python 中的通用命令模式和命令调度模式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1494442/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
General Command pattern and Command Dispatch pattern in Python
提问by legesh
I was looking for a Commandpattern implementation in Python... (According to Wikipedia,
我正在寻找Python 中的命令模式实现......(根据维基百科,
the command pattern is a design pattern in which an object is used to represent and encapsulate all the information needed to call a method at a later time.
命令模式是一种设计模式,其中对象用于表示和封装以后调用方法所需的所有信息。
)
)
The only thing I found was 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()
May be I'm wrong, but it looks like these are two different concepts, which accidentally have similar names.
可能是我错了,但看起来这是两个不同的概念,它们不小心具有相似的名称。
Am i missing something?
我错过了什么吗?
回答by Ants Aasma
The simplest command pattern is already built into Python, simply use a callable:
最简单的命令模式已经内置到 Python 中,只需使用一个可调用的:
def greet(who):
print "Hello %s" % who
greet_command = lambda: greet("World")
# pass the callable around, and invoke it later
greet_command()
The command pattern as an object oriented design pattern makes more sense if your commands need to be able to do more than just be invoked. Common usecase is when you need to be able to undo/redo your actions. Then a command class is a good way to couple the forward and backwards actions together. For example:
如果您的命令需要能够做的不仅仅是被调用,那么命令模式作为面向对象的设计模式更有意义。常见用例是当您需要能够撤消/重做您的操作时。那么命令类是将向前和向后动作耦合在一起的好方法。例如:
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
回答by Martin v. L?wis
Yes, you do miss something: the command pattern is only necessary in languages that don't have function pointers (or functions as first class objects), such as Java. In languages with functions-as-objects, you can use the function itself; no need to have a separate command object (which then should have a "doit" method).
是的,您确实错过了一些东西:命令模式仅在没有函数指针(或函数作为第一类对象)的语言中才是必需的,例如 Java。在将函数作为对象的语言中,您可以使用函数本身;不需要有一个单独的命令对象(然后应该有一个“doit”方法)。
In the example could you quote, the getattr()
call gives you the "command object" (i.e. the bound method); adding parenthesis after it "invokes" (i.e. calls) the command object.
在示例中,您可以引用,getattr()
调用为您提供“命令对象”(即绑定方法);在它“调用”(即调用)命令对象之后添加括号。
回答by FModa3
Did some searching and found this. It appears to do the job of encapsulating an action.
做了一些搜索,发现了这个。它似乎完成了封装动作的工作。
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)
回答by Ned Batchelder
If I recall the gang of four correctly, the Command pattern is about commands like "File - Save", not commands like "svn commit", which is what your code is good for.
如果我没记错四人组,命令模式是关于像“文件 - 保存”这样的命令,而不是像“svn commit”这样的命令,这是你的代码所擅长的。
Martin suggests the Command pattern is unneeded because functions as first class objects take its place, but the Command pattern is richer than just doit()
, having, for example, also undo()
, is_enabled()
, etc.
马丁建议Command模式是不需要的,因为函数作为第一类对象代替它,但Command模式不仅仅是丰富doit()
,有,例如,还undo()
,is_enabled()
等等。