一、飯店點餐系統(tǒng)
又是一個點餐系統(tǒng)(原諒作者的吃貨屬性)。不過這次的點餐系統(tǒng)是個飯店的點餐系統(tǒng)。飯店的點餐系統(tǒng)有什么不同嘛?大伙想想看,在大多數(shù)飯店中,當(dāng)服務(wù)員已經(jīng)接到顧客的點單,錄入到系統(tǒng)中后,根據(jù)不同的菜品,會有不同的后臺反應(yīng)。比如,飯店有涼菜間、熱菜間、主食間,那當(dāng)服務(wù)員將菜品錄入到系統(tǒng)中后,涼菜間會打印出顧客所點的涼菜條目,熱菜間會打印出顧客所點的熱菜條目,主食間會打印出主食條目。那這個系統(tǒng)的后臺模式該如何設(shè)計?當(dāng)然,直接在場景代碼中加if…else…語句判斷是個方法,可這樣做又一次加重了系統(tǒng)耦合,違反了單一職責(zé)原則,遇到系統(tǒng)需求變動時,又會輕易違反開閉原則。所以,我們需要重新組織一下結(jié)構(gòu)。
可以將該系統(tǒng)設(shè)計成前臺服務(wù)員系統(tǒng)和后臺系統(tǒng),后臺系統(tǒng)進一步細(xì)分成主食子系統(tǒng),涼菜子系統(tǒng),熱菜子系統(tǒng)。后臺三個子系統(tǒng)設(shè)計如下:
class backSys():
def cook(self,dish):
pass
class 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
前臺服務(wù)員系統(tǒng)與后臺系統(tǒng)的交互,我們可以通過命令的模式來實現(xiàn),服務(wù)員將顧客的點單內(nèi)容封裝成命令,直接對后臺下達(dá)命令,后臺完成命令要求的事,即可。前臺系統(tǒng)構(gòu)建如下:
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:Nofify..."
for command in self.commandList:
command.execute()
前臺系統(tǒng)中的notify接口直接調(diào)用命令中的execute接口,執(zhí)行命令。命令類構(gòu)建如下:
class Command():
receiver = None
def __init__(self, receiver):
self.receiver = receiver
def execute(self):
pass
class 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):
pass
class coolDishCommand(foodCommand):
pass
class hotDishCommand(foodCommand):
pass
Command類是個比較通過的類,foodCommand類是本例中涉及的類,相比于Command類進行了一定的改造。由于后臺系統(tǒng)中的執(zhí)行函數(shù)都是cook,因而在foodCommand類中直接將execute接口實現(xiàn),如果后臺系統(tǒng)執(zhí)行函數(shù)不同,需要在三個子命令系統(tǒng)中實現(xiàn)execute接口。這樣,后臺三個命令類就可以直接繼承,不用進行修改了。(這里子系統(tǒng)沒有變動,可以將三個子系統(tǒng)的命令廢棄不用,直接用foodCommand嗎?當(dāng)然可以,各有利蔽。請讀者結(jié)合自身開發(fā)經(jīng)驗,進行思考相對于自己業(yè)務(wù)場景的使用,哪種方式更好。)
為使場景業(yè)務(wù)精簡一些,我們再加一個菜單類來輔助業(yè)務(wù),菜單類在本例中直接寫死。
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
業(yè)務(wù)場景如下:
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:Nofify...
HOTDISH:Cook Yu-Shiang Shredded Pork
HOTDISH:Cook Sauteed Tofu, Home Style
COOLDISH:Cook Cucumber
MAINFOOD:Cook Rice
二、命令模式
命令模式的定義為:將一個請求封裝成一個對象,從而可以使用不同的請求將客戶端參數(shù)化,對請求排隊或者記錄請求日志,可以提供命令的撤銷和恢復(fù)功能。命令模式中通常涉及三類對象的抽象:Receiver,Command,Invoker(本例中的waiterSys)。

只有一個Invoker的命令模式也可以抽象成一個類似的“星形網(wǎng)絡(luò)”,但與之前介紹的中介者模式不同,單純的命令模式更像是一個輻射狀的結(jié)構(gòu),由Invoker直接對Receiver傳遞命令,而一般不反向傳遞,中介者模式“星形網(wǎng)絡(luò)”的中心,是個協(xié)調(diào)者,抽象結(jié)節(jié)間的信息流全部或者部分是雙向的。
另外,命令模式的定義中提到了“撤銷和恢復(fù)功能”,也給了各位開發(fā)人員一個命令模式使用過程中的建議:各個Receiver中可以設(shè)計一個回滾接口,支持命令的“撤銷”。
三、命令模式的優(yōu)點和應(yīng)用場景
優(yōu)點:
1、低耦合:調(diào)用者和接收者之間沒有什么直接關(guān)系,二者通過命令中的execute接口聯(lián)系;
2、擴展性好:新命令很容易加入,也很容易拼出“組合命令”。
應(yīng)用場景:
1、觸發(fā)-反饋機制的系統(tǒng),都可以使用命令模式思想。如基于管道結(jié)構(gòu)的命令系統(tǒng)(如SHELL),可以直接套用命令模式;此外,GUI系統(tǒng)中的操作反饋(如點擊、鍵入等),也可以使用命令模式思想。
四、命令模式的缺點
1、如果業(yè)務(wù)場景中命令比較多,那么對應(yīng)命令類和命令對象的數(shù)量也會增加,這樣系統(tǒng)會膨脹得很大。