Python中的通用命令模式和命令调度模式

27 投票
4 回答
18313 浏览
提问于 2025-04-15 14:41

我在找Python中的命令模式实现...

(根据维基百科

命令模式是一种设计模式,它用一个对象来表示和封装调用某个方法所需的所有信息,以便在以后某个时候使用。

)

我找到的唯一内容是命令分发模式

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 个回答

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

是的,你确实漏掉了一些东西:命令模式在那些没有函数指针(或者说没有把函数当作第一类对象的语言)中才是必要的,比如Java。在那些可以把函数当作对象的语言中,你可以直接使用函数本身;不需要单独创建一个命令对象(这个对象还得有个“doit”方法)。

在你提到的例子中,getattr() 调用给你返回了“命令对象”(也就是绑定的方法);在它后面加上括号就是“调用”这个命令对象。

65

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

撰写回答