舉個慄子 路邊攤吃燒烤,老闆只有一人,又要記住點單,又要忙著收費,客戶做什麼都要排隊。。。 反例思路1 如果客戶多了,請求多,就容易混亂,他叫五串羊肉串,你叫三個烤雞翅,老闆哪裡忙得過來。代碼中的體現就是一句一句輸出,所以應該要有個服務員。。。 門面改造 Talk is cheap, show me ...
舉個慄子
路邊攤吃燒烤,老闆只有一人,又要記住點單,又要忙著收費,客戶做什麼都要排隊。。。
反例思路1
如果客戶多了,請求多,就容易混亂,他叫五串羊肉串,你叫三個烤雞翅,老闆哪裡忙得過來。代碼中的體現就是一句一句輸出,所以應該要有個服務員。。。
門面改造
Talk is cheap, show me the code
(屁話少說,放碼過來)
/**
* 抽象命令
* Created by callmeDevil on 2019/12/14.
*/
public abstract class Command {
protected Barbecuer receiver;
public Command(Barbecuer receiver){
this.receiver = receiver;
}
// 執行命令
public abstract void excuteCommand();
}
/**
* 烤羊肉串命令
* Created by callmeDevil on 2019/12/14.
*/
public class BakeMuttonCommand extends Command{
public BakeMuttonCommand(Barbecuer receiver){
super(receiver);
}
@Override
public void excuteCommand() {
receiver.bakeMutton();
}
}
/**
* 烤雞翅命令
* Created by callmeDevil on 2019/12/14.
*/
public class BakeChickenWingCommand extends Command{
public BakeChickenWingCommand(Barbecuer receiver){
super(receiver);
}
@Override
public void excuteCommand() {
receiver.bakeChickenWing();
}
}
/**
* 烤肉串者
* Created by callmeDevil on 2019/12/14.
*/
public class Barbecuer {
public void bakeMutton(){
System.out.println("烤羊肉串!");
}
public void bakeChickenWing(){
System.out.println("烤雞翅!");
}
}
/**
* 服務員
* Created by callmeDevil on 2019/12/14.
*/
public class Waiter {
private Command command;
// 不管什麼用戶想要什麼烤肉,反正都是命令,只管記錄訂單,然後通知烤肉串者即可
public void setOrder(Command command){
this.command = command;
}
public void notifying(){
command.excuteCommand();
}
}
public class Test {
public static void main(String[] args) {
// 開店前的準備
Barbecuer boy = new Barbecuer();
Command bakeMuttonCommand1 = new BakeMuttonCommand(boy);
Command bakeMuttonCommand2 = new BakeMuttonCommand(boy);
BakeChickenWingCommand bakeChickenWingCommand1 = new BakeChickenWingCommand(boy);
Waiter girl = new Waiter();
// 開門營業
girl.setOrder(bakeMuttonCommand1);
girl.notifying();
girl.setOrder(bakeMuttonCommand2);
girl.notifying();
girl.setOrder(bakeChickenWingCommand1);
girl.notifying();
}
}
運行結果
烤羊肉串!
烤羊肉串!
烤雞翅!
其實服務員那裡可以完善,比如點單的時候不是一個一個點,而是點完之後一起給單;而且尚未烤肉時,訂單也可以進行更改或取消,烤肉的人也是很多肉一起烤,等等,此處就不優化了。
命令模式
定義
將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可撤銷的操作。
UML圖
總結
- 它能較容易的設計一個命令隊列
- 在需要的情況下,可以較容易的將命令記入日誌
- 允許接收請求的一方決定是否要取消請求
- 可以容易的實現對請求的撤銷和重做
- 由於加進新的具體命令類不影響其他的類,因此增加新的具體命令類很容易
- 最關鍵的就是命令模式把請求一個操作的對象與知道怎麼執行一個操作的對象分割開(服務員和烤肉串者)。
是否碰到如撤銷/恢復功能等類似的情況就一定要實現命令模式?
敏捷開發原則告訴我們,不要為代碼添加基於猜測的、實際不需要的功能。如果不清楚一個系統是否需要命令模式,一般就不要著急去實現它,事實上,在需要的時候通過重構實現這個模式並不困難,只要在真正需要如撤銷/恢復操作等功能時,把原來的代碼重構為命令模式才有意義。