命令模式
1、內容
命令模式是一個高內聚的模式,其定義為:Encapsulate a request as an object,there by letting you parameterize clients with different requests,queue or log requests,and support undoable operations.(將一個請求封裝成一個物件,從而讓你使用不同的請求把客戶端引數化,對請 求排隊或者記錄請求日誌,可以提供命令的撤銷和恢復功能。)
2、角色
Receiver接受者角色:該角色就是幹活的角色,命令傳遞到這裡是應該被執行Command命令角色:需要執行的所有命令都在這裡宣告 Invoker呼叫者角色:接收到命令,並執行命令
**3、優點 **
類間解耦:呼叫者角色與接收者角色之間沒有任何依賴關係,呼叫者實現功能時只需呼叫Command 抽象類的execute方法就可以,不需要了解到底是哪個接收者執行。
可擴充套件性:Command的子類可以非常容易地擴充套件,而呼叫者Invoker和高層次的模組Client不產生嚴 重的程式碼耦合。
命令模式結合其他模式會更優秀:命令模式可以結合責任鏈模式,實現命令族解析任務;結合模板方法模式,則可以減少 Command子類的膨脹問題。
4、缺點
命令模式也是有缺點的,請看Command的子類:如果有N個命令,問題就出來 了,Command的子類就可不是幾個,而是N個,這個類膨脹得非常大,這個就需要讀者在項 目中慎重考慮使用。
5、程式碼示例
命令模式
在請求者和請求實現者之間,把請求抽象成命令,並新增一個命令接受和分發者,實現請求者和實現者的解耦
如客戶(請求者)去燒烤店吃飯,並不需要認識燒烤boy(實現者),只需要有選單(命令),服務員(命令接收和分發者),然後根據
選單給服務員下單就好了。然後選單有會有記錄,我們可以要求撤銷和重做,燒烤店可以拒絕我們的某個選單。
優點:1、可以有一個命令列表;2、命令可以很容易寫入日誌;3、命令可以被撤銷或重做;4、命令實現者可以拒絕命令;5、實現了請求者
和實現者的解耦;6、要加入新的命令很容易,增加個命令類,實現者能做對應的命令
複製程式碼
from abc import ABCMeta, abstractmethod
class Cooker(object):
"""
廚師
"""
def __init__(self):
self._num_yang = 1
self._num_niu = 1
def cook_yang(self):
if self._num_yang <= 3:
print("燒烤羊肉串")
self._num_yang += 1
else:
print("沒羊肉串了")
def cook_niu(self):
if self._num_niu <= 3:
print("燒烤牛肉串")
self._num_niu += 1
else:
print("沒牛肉串了")
class Command(object):
"""
抽象選單
"""
__metaclass__ = ABCMeta
def __init__(self, name):
self.cooker = Cooker()
self.name = name
@abstractmethod
def cook(self):
pass
class CommandYang(Command):
def __init__(self, name):
super(CommandYang, self).__init__(name)
def cook(self):
self.cooker.cook_yang()
class CommandNiu(Command):
def __init__(self, name):
super(CommandNiu, self).__init__(name)
def cook(self):
self.cooker.cook_niu()
class Waiter(object):
def __init__(self):
self._command_list = []
self._menu = None
self._kehu = None
def set_kehu(self, kehu):
self._kehu = kehu
def set_order(self, command, num=1):
print("加菜:" + command.name)
for i in range(num):
self._command_list.append(command)
def remove_order(self, command, num=1):
print("減菜:" + command.name)
try:
for i in range(num):
self._command_list.remove(command)
except Exception as e:
print("沒點那麼多菜")
def notify(self):
print("下單啦:")
self._menu = Order(self._kehu, self._command_list)
self._menu.show()
for command in self._command_list:
command.cook()
self._command_list = []
print("")
class Order(object):
def __init__(self, name, command_list):
self._command_list = command_list
self._name = name
def set_order(self, command_list):
self._command_list = command_list
def set_name(self, name):
self._name = name
def show(self):
print(self._name + ",您的選單是:")
for command in self._command_list:
print(command.name)
print("")
if __name__ == '__main__':
# 燒烤店初始化
command_yang = CommandYang("羊肉串")
command_niu = CommandNiu("牛肉串")
waiter = Waiter()
# 營業
waiter.set_kehu("張三")
waiter.set_order(command_yang, 4)
waiter.set_order(command_niu, 5)
waiter.notify()
複製程式碼