設(shè)計(jì)模式中有六大原則和二十三設(shè)計(jì)模式。
其中六大原則分別為:?jiǎn)我宦氊?zé)原則、開(kāi)閉原則、里氏替換原則、依賴(lài)倒置原則、接口隔離原則、迪米特原則。
二十三設(shè)計(jì)模式:?jiǎn)卫J?、Builder 模式、原型模式、工廠(chǎng)方法模式、抽象工廠(chǎng)模式、策略模式、狀態(tài)模式、責(zé)任鏈模式、解釋器模式、命令模式、觀察者模式、備忘錄模式、迭代器模式、模版方法模式、訪(fǎng)問(wèn)者模式、中介模式、代理模式、組合模式、適配器模式、裝飾模式、享元模式、外觀模式、橋接模式。
命令模式,看這個(gè)名字就知道它是以命令為終極目標(biāo),比如開(kāi)機(jī)命令、關(guān)機(jī)命令等。
命令模式相對(duì)于其他設(shè)計(jì)模式來(lái)說(shuō),它并沒(méi)有那么多的條條框框,它不是一個(gè)“規(guī)矩”的模式,它比其他模式更加靈活多變。
定義
將一個(gè)請(qǐng)求封裝成一個(gè)對(duì)象,從而讓用戶(hù)使用不同的請(qǐng)求把客戶(hù)端參數(shù)化;對(duì)請(qǐng)求排隊(duì)或者記錄請(qǐng)求日志,以及支持可撤銷(xiāo)的操作。
使用場(chǎng)景
認(rèn)為是命令的地方都可以使用命令模式。
- 系統(tǒng)需要將請(qǐng)求調(diào)用者和請(qǐng)求接收者解耦,使得調(diào)用者和接收者不直接交互
- 系統(tǒng)需要在不同的時(shí)間指定請(qǐng)求、將請(qǐng)求排隊(duì)和執(zhí)行請(qǐng)求
- 系統(tǒng)需要支持命令的撤銷(xiāo)(Undo)操作和恢復(fù)(Redo)操作
- 系統(tǒng)需要將一組操作組合在一起,即支持宏命令
優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 降低耦合度
- 靈活性更高,新的命令可以很容易加到系統(tǒng)中
- 實(shí)現(xiàn)簡(jiǎn)單,可以比較容易的設(shè)計(jì)一個(gè)命令
- 調(diào)用同一方法實(shí)現(xiàn)不同功能
缺點(diǎn)
- 類(lèi)爆炸,使用命令模式可能會(huì)導(dǎo)致某些系統(tǒng)有過(guò)多的具體命令類(lèi)
UML圖

- Receiver:接收者角色。負(fù)責(zé)具體實(shí)施或執(zhí)行一個(gè)請(qǐng)求,真正執(zhí)行命令的對(duì)象。任何類(lèi)都可能成為一個(gè)接收者,只要它能夠?qū)崿F(xiàn)命令要求實(shí)現(xiàn)的相應(yīng)功能
- Command:命令角色。定義所有具體命令類(lèi)的抽象接口
- ConcreteCommand:具體命令角色。命令接口實(shí)現(xiàn)對(duì)象,是“虛”的實(shí)現(xiàn);通常會(huì)持有接收者,并調(diào)用接收者的功能來(lái)完成命令要執(zhí)行的操作
- Invoker:請(qǐng)求者角色。要求命令對(duì)象執(zhí)行請(qǐng)求,通常會(huì)持有命令對(duì)象,可以持有很多的命令對(duì)象。這個(gè)是客戶(hù)端真正觸發(fā)命令并要求命令執(zhí)行相應(yīng)操作的地方,也就是說(shuō)相當(dāng)于使用命令對(duì)象的入口
代碼實(shí)現(xiàn)
- 接收者
/**
* 接收者
*/
public class Receiver {
// 執(zhí)行具體命令邏輯的方法
public void action1(){
System.out.println("執(zhí)行具體操作邏輯1");
}
}
- 命令角色
/**
* 命令接口
*/
public interface Command {
/**
* 執(zhí)行命令
*/
void execute();
}
- 命令具體實(shí)現(xiàn)
/**
* 具體命令角色
*/
public class ConcreteCommand1 implements Command {
private Receiver receiver;
public ConcreteCommand1(Receiver receiver) {
this.receiver = receiver;
}
/**
* 執(zhí)行命令
*/
@Override
public void execute() {
// 調(diào)用接收者的相關(guān)方法來(lái)執(zhí)行具體邏輯
receiver.action1();
}
}
- 請(qǐng)求者角色
/**
* 請(qǐng)求者角色
*/
public class Invoker {
private Command command1;
/**
* 執(zhí)行請(qǐng)求方法
*/
public void action1(){
// 調(diào)用具體命令對(duì)象的相關(guān)方法,執(zhí)行具體命令
command1.execute();
}
public Command getCommand1() {
return command1;
}
public void setCommand1(Command command1) {
this.command1 = command1;
}
}
- 執(zhí)行
public static void main(String[] args) {
// 定義接收者(執(zhí)行具體邏輯)
Receiver receiver =new Receiver();
// 根據(jù)接收者構(gòu)造具體命令對(duì)象
Command command1 = new ConcreteCommand1(receiver);
Command command2 = new ConcreteCommand2(receiver);
// 根據(jù)命令對(duì)象構(gòu)造請(qǐng)求對(duì)象
Invoker invoker = new Invoker();
invoker.setCommand1(command1);
invoker.setCommand2(command2);
// 發(fā)送命令請(qǐng)求
invoker.action1();
invoker.action2();
}
- 結(jié)果
執(zhí)行具體操作邏輯1
執(zhí)行具體操作邏輯2
總結(jié)
命令模式看起來(lái)和策略模式很像(策略模式好像和所有模式都好像??♂?),
Command模式用于從需要完成的操作中創(chuàng)建一個(gè)對(duì)象 - 獲取操作及其參數(shù)并將它們包裝在要記錄的對(duì)象中,保留用于撤消隨著時(shí)間的推移,將會(huì)有大量不同的Command對(duì)象通過(guò)系統(tǒng)中的給定點(diǎn),并且Command對(duì)象將包含描述所請(qǐng)求操作的不同參數(shù)。
策略模式則用于指定如何應(yīng)該完成的事情,并插入更大的對(duì)象或方法以提供特定的算法。排序策略可能是合并排序,可能是插入排序,也可能是更復(fù)雜的事情,如果列表大于某個(gè)最小大小,則僅使用合并排序。策略對(duì)象很少受到Command對(duì)象的大規(guī)?;靵y,而是經(jīng)常用于配置或調(diào)優(yōu)目的。
這兩種模式都涉及將包含它們的原始類(lèi)中的單個(gè)操作的代碼和可能的參數(shù)分解為另一個(gè)對(duì)象以提供獨(dú)立的可變性。不同之處在于實(shí)踐中遇到的用例以及每種模式背后的意圖。
DEMO
參考
《Android 源碼設(shè)計(jì)模式解析與實(shí)踐》
策略模式和命令模式的不同