命令模式(Command Pattern)是一種數(shù)據(jù)驅(qū)動的設(shè)計模式赎瞎,它屬于行為型模式。請求以命令的形式包裹在對象中,并傳給調(diào)用對象仰楚。調(diào)用對象尋找可以處理該命令的合適的對象,并把該命令傳給相應(yīng)的對象,該對象執(zhí)行命令僧界。
介紹
意圖:將一個請求封裝成一個對象侨嘀,從而使您可以用不同的請求對客戶進行參數(shù)化。
主要解決:在軟件系統(tǒng)中捂襟,行為請求者與行為實現(xiàn)者通常是一種緊耦合的關(guān)系咬腕,但某些場合,比如需要對行為進行記錄笆豁、撤銷或重做郎汪、事務(wù)等處理時,這種無法抵御變化的緊耦合的設(shè)計就不太合適闯狱。
何時使用:在某些場合煞赢,比如要對行為進行"記錄、撤銷/重做哄孤、事務(wù)"等處理照筑,這種無法抵御變化的緊耦合是不合適的。在這種情況下瘦陈,如何將"行為請求者"與"行為實現(xiàn)者"解耦凝危?將一組行為抽象為對象,可以實現(xiàn)二者之間的松耦合晨逝。
如何解決:通過調(diào)用者調(diào)用接受者執(zhí)行命令蛾默,順序:調(diào)用者→接受者→命令。
關(guān)鍵代碼:定義三個角色:1捉貌、received 真正的命令執(zhí)行對象 2支鸡、Command 3、invoker 使用命令對象的入口
應(yīng)用實例:struts 1 中的 action 核心控制器 ActionServlet 只有一個趁窃,相當于 Invoker牧挣,而模型層的類會隨著不同的應(yīng)用有不同的模型類,相當于具體的 Command醒陆。
優(yōu)點: 1瀑构、降低了系統(tǒng)耦合度。 2刨摩、新的命令可以很容易添加到系統(tǒng)中去寺晌。
缺點:使用命令模式可能會導(dǎo)致某些系統(tǒng)有過多的具體命令類。
使用場景:認為是命令的地方都可以使用命令模式码邻,比如: 1折剃、GUI 中每一個按鈕都是一條命令。 2像屋、模擬 CMD怕犁。
注意事項:系統(tǒng)需要支持命令的撤銷(Undo)操作和恢復(fù)(Redo)操作,也可以考慮使用命令模式,見命令模式的擴展奏甫。
上代碼
構(gòu)建一個買東西的場景戈轿。貨物可以進貨和賣出。進貨和賣出都是命令阵子。有個Broker經(jīng)紀人思杯,負責倒騰貨物,有一個命令集合的成員變量挠进,有2個方法色乾,一個是增加命令,一個是執(zhí)行所有命令(命令集合)领突。
//命令抽象接口
public interface Order {
void execute(); //執(zhí)行命令
}
/*
貨物抽象接口暖璧。 可以進貨或者賣掉
*/
public interface Good {
void takeIn();
void sell();
}
/*
經(jīng)紀人 負責倒騰貨物
有一個命令的集合
主要有2個方法,一個是添加一條命令君旦,一個是執(zhí)行所有命令然后清空命令集合
*/
public class Broker {
List<Order> orderList = new ArrayList<Order>();
public void addOrder(Order order){
this.orderList.add(order);
}
public void doOrders(){
for (Order order:orderList) {
order.execute();
}
this.orderList.clear();
}
}
//具體貨物實現(xiàn)類
public class SomeGood implements Good {
public void takeIn() {
System.out.println("somegood 進貨");
}
public void sell() {
System.out.println("somegood 賣貨");
}
}
//進貨命令 執(zhí)行g(shù)ood的進貨方法
public class TakeInOrder implements Order {
private Good good;
public TakeInOrder(Good good){
this.good = good;
}
public void execute() {
this.good.takeIn();
}
}
//賣出命令澎办,執(zhí)行貨物的銷售方法
public class SellOrder implements Order {
private Good good;
public SellOrder(Good good){
this.good = good;
}
public void execute() {
this.good.sell();
}
}
//測試類
public class CommandClient {
public static void main(String[] args) {
Good someGood = new SomeGood();
Order takeInOrder = new TakeInOrder(someGood);
Order sellOrder = new SellOrder(someGood);
Broker broker = new Broker();
broker.addOrder(takeInOrder);
broker.addOrder(takeInOrder); //添加2次進貨命令
broker.addOrder(sellOrder); //一次售出命令
broker.doOrders();
}
}
結(jié)果
somegood 進貨
somegood 進貨
somegood 賣貨