2009-09-29 237 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