標籤:相互 list pre 內容 ret AC 使用命令 lse 按鈕
說明:
命令在發送方被啟用,而在接收方被響應。一個對象既可以作為命令的發送方,也可以作為命令的接收方,或者都可以。命令的典型應用就是圖形化使用者介面開發。每一個表單都包含菜單,工具列,按鈕等控制項,將使用者的單機動作也叫命令作為外來事件,然後系統會根據綁定的事件處理常式執行相應的動作即命令獲得響應,完成使用者發出的請求。
大多數情況下,命令的調用者和接收者是前期綁定的,但是想要對命令進行操作的時候,就需要撤銷命令的調用者和接收者之間的緊密耦合關係,使得二者相互獨立。
命令模式(Command Pattern):將請求封裝成對象,將其作為命令調用者和接收者的中介,而抽象出來的命令對象又使得能夠對一系列請求進行特殊操作,比如:對請求排隊或記錄請求日誌,以及支援可撤消的操作.
結構組成:
命令角色,具體命令角色,接收者角色,要求者(調用者)角色(Invoker),客戶角色(Client)
執行個體:
在大多數飯店中,當服務員已經接到顧客的點單,錄入到系統中後,根據不同的菜品,會有不同的後台反應。比如,飯店有涼菜間、熱菜間、主食間,那當服務員將菜品錄入到系統中後,涼菜間會列印出顧客所點的涼菜條目,熱菜間會列印出顧客所點的熱菜條目,主食間會列印出主食條目。那這個系統的後台模式該如何設計?當然,直接在情境代碼中加if…else…語句判斷是個方法,可這樣做又一次加重了系統耦合,違反了單一職責原則,遇到系統需求變動時,又會輕易違反開閉原則。所以,我們需要重新組織一下結構。可以將該系統設計成前台服務員系統和後台系統,後台系統進一步細分成主食子系統,涼菜子系統,熱菜子系統。
#主食子系統,涼菜子系統,熱菜子系統,後台三個子系統class backSys(): def cook(self,dish): passclass mainFoodSys(backSys): def cook(self,dish): print("MAINFOOD:Cook %s"%dish)class coolDishSys(backSys): def cook(self,dish): print("COOLDISH:Cook %s"%dish)class hotDishSys(backSys): def cook(self,dish): print("HOTDISH:Cook %s"%dish)#前台服務員系統與後台系統的互動,我們可以通過命令的模式來實現,#服務員將顧客的點單內容封裝成命令,直接對後台下達命令,後台完成命令要求的事,#前台系統構建如下class waiterSys(): menu_map=dict() commandList=[] def setOrder(self,command): print("WAITER:Add dish") self.commandList.append(command) def cancelOrder(self,command): print("WAITER:Cancel order...") self.commandList.remove(command) def notify(self): print("WAITER:Notify...") for command in self.commandList: command.execute()#前台系統中的notify介面直接調用命令中的execute介面,執行命令。命令類構建class Command(): receiver = None def __init__(self, receiver): self.receiver = receiver def execute(self): passclass foodCommand(Command): dish="" def __init__(self,receiver,dish): self.receiver=receiver self.dish=dish def execute(self): self.receiver.cook(self.dish)class mainFoodCommand(foodCommand): passclass coolDishCommand(foodCommand): passclass hotDishCommand(foodCommand): pass"""Command類是個比較通過的類,foodCommand類是本例中涉及的類,相比於Command類進行了一定的改造。由於後台系統中的執行函數都是cook,因而在foodCommand類中直接將execute介面實現,如果後台系統執行函數不同,需要在三個子命令系統中實現execute介面。這樣,後台三個命令類就可以直接繼承,不用進行修改了。"""#菜單類輔助業務class menuAll: menu_map=dict() def loadMenu(self):#載入菜單,這裡直接寫死 self.menu_map["hot"] = ["Yu-Shiang Shredded Pork", "Sauteed Tofu, Home Style", "Sauteed Snow Peas"] self.menu_map["cool"] = ["Cucumber", "Preserved egg"] self.menu_map["main"] = ["Rice", "Pie"] def isHot(self,dish): if dish in self.menu_map["hot"]: return True return False def isCool(self,dish): if dish in self.menu_map["cool"]: return True return False def isMain(self,dish): if dish in self.menu_map["main"]: return True return False#業務情境if __name__=="__main__": dish_list=["Yu-Shiang Shredded Pork","Sauteed Tofu, Home Style","Cucumber","Rice"]#顧客點的菜 waiter_sys=waiterSys() main_food_sys=mainFoodSys() cool_dish_sys=coolDishSys() hot_dish_sys=hotDishSys() menu=menuAll() menu.loadMenu() for dish in dish_list: if menu.isCool(dish): cmd=coolDishCommand(cool_dish_sys,dish) elif menu.isHot(dish): cmd=hotDishCommand(hot_dish_sys,dish) elif menu.isMain(dish): cmd=mainFoodCommand(main_food_sys,dish) else: continue waiter_sys.setOrder(cmd) waiter_sys.notify()
列印結果:
WAITER:Add dish
WAITER:Add dish
WAITER:Add dish
WAITER:Add dish
WAITER:Notify...
HOTDISH:Cook Yu-Shiang Shredded Pork
HOTDISH:Cook Sauteed Tofu, Home Style
COOLDISH:Cook Cucumber
MAINFOOD:Cook Rice
優點:降低對象之間的耦合度。新的命令可以很容易地加入到系統中。可以比較容易地設計一個組合命令。調用同一方法實現不同的功能缺點:使用命令模式可能會導致某些系統有過多的具體命令類。因為針對每一個命令都需要設計一個具體命令類,因此某些系統可能需要大量具體命令類,這將影響命令模式的使用。適用性:
系統需要將請求調用者和請求接收者解耦,使得調用者和接收者不直接互動。
在不同的時刻指定、排列和執行請求。
支援修改日誌、撤銷操作。
系統需要將一組操作組合在一起,即支援宏命令。
python-命令模式