介紹
將一個請求封裝為一個對象,從而使我們可用不同的請求對客戶進行參數(shù)化;對請求排隊或者記錄請求日志,以及支持可撤銷的操作匙奴。也稱之為:動作(Action)模式堆巧、事物(transaction)模式
結(jié)構(gòu)
- Command抽象命令類
- ConcreteCommand具體命令類
- Invoker調(diào)用者/請求者
請求的發(fā)送者,它通過命令對象來執(zhí)行請求泼菌。一個調(diào)用者并不需要在設(shè)計時確定其接收者谍肤,因此它只與抽象命令類之間存在關(guān)聯(lián)。在程序運行時哗伯,將調(diào)用命令對象的execute(),間接調(diào)用接收者的相關(guān)操作荒揣。 - Receiver接收者
接收者執(zhí)行與請求相關(guān)的操作,具體實現(xiàn)對請求的業(yè)務(wù)處理。
未抽象前焊刹,實際執(zhí)行操作內(nèi)容的對象系任。 -
Client客戶類
在客戶類中需要創(chuàng)建調(diào)用者對象、具體命令類對象虐块,在創(chuàng)建具體命令對象時指定對應(yīng)的接收者俩滥。發(fā)送和接收者之間沒有直接關(guān)系,都通過命令對象間接調(diào)用贺奠。
命令模式
package command;
public class Receiver {
public void action(){
System.out.println("Receiver.action()");
}
}
package command;
public interface Command {
// 實際項目中,可以根據(jù)需求設(shè)計多個不同的方法
void execute();
}
class ConcreteCommand implements Command{
private Receiver receiver; // 命令正真的執(zhí)行者
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
public void execute() {
// 可以在命令正真執(zhí)行前后,執(zhí)行相關(guān)處理
receiver.action();
}
}
package command;
public class Invoker {
private Command command; //也可以通過容器List<Command>容納多個命令對象,進行批處理
public Invoker(Command command) {
this.command = command;
}
// 業(yè)務(wù)方法,用于調(diào)用命令類的方法
public void call(){
command.execute();
}
}
package command;
public class Client {
public static void main(String[] args) {
Command command = new ConcreteCommand(new Receiver());
Invoker invoker = new Invoker(command);
invoker.call();
}
}
開發(fā)中常見的場景
- Struts2中霜旧,action的整個調(diào)用過程中就有命令模式。
- 數(shù)據(jù)庫事物機制的底層實現(xiàn)
- 命令的撤銷和恢復(fù)
優(yōu)點
- 它能比較容易地設(shè)計一個命令隊列儡率;
- 在需要的情況下挂据,可以較容易地將命令記入日志;
- 允許接收請求的一方?jīng)Q定是否要否決請求儿普;
- 可以容易地實現(xiàn)對請求的撤銷和重做崎逃;
- 由于加進新的具體命令類不影響其他類,因此增加新的具體命令類很容易箕肃;
- 命令模式吧請求一個操作的對象與知道怎么執(zhí)行一個操作的對象分割開婚脱;
敏捷開發(fā)原則告訴我們,不要為代碼添加基于猜測的、實際不需要的功能勺像。如果不清楚一個系統(tǒng)是否需要命令模式障贸,一般就不要著急去實現(xiàn)它,事實上吟宦,在需要的時候通過重構(gòu)實現(xiàn)這個模式并不困難篮洁,只有在真正需要如撤銷/恢復(fù)操作等功能時,把原來的代碼重構(gòu)為命令模式才有意義。