介紹
說到命令模式,我們可以聯(lián)想到上級(jí)下達(dá)命令珠月,下級(jí)接收命令去執(zhí)行扩淀,遙控器發(fā)送命令,相應(yīng)的機(jī)器做出反應(yīng)啤挎。就比如電燈泡的開關(guān)驻谆,排氣扇的開關(guān)等等。這些開關(guān)就是發(fā)送命令的對(duì)象庆聘,而電燈泡和排氣扇就是接受命令的對(duì)象胜臊,如下圖。
命令模式(Command Pattern)是一種數(shù)據(jù)驅(qū)動(dòng)的設(shè)計(jì)模式伙判,它屬于行為型模式象对。請(qǐng)求以命令的形式包裹在對(duì)象中,并傳給調(diào)用對(duì)象澳腹。調(diào)用對(duì)象尋找可以處理該命令的合適的對(duì)象织盼,并把該命令傳給相應(yīng)的對(duì)象杨何,該對(duì)象執(zhí)行命令。命令模式可以對(duì)發(fā)送者和接收者完全解耦沥邻,發(fā)送者與接收者之間沒有直接引用關(guān)系危虱,發(fā)送請(qǐng)求的對(duì)象只需要知道如何發(fā)送請(qǐng)求,而不必知道如何完成請(qǐng)求唐全。這就是命令模式的模式動(dòng)機(jī)埃跷。
角色
● Command(抽象命令類):抽象命令類一般是一個(gè)抽象類或接口,在其中聲明了用于執(zhí)行請(qǐng)求的execute()等方法邮利,通過這些方法可以調(diào)用請(qǐng)求接收者的相關(guān)操作弥雹。
● ConcreteCommand(具體命令類):具體命令類是抽象命令類的子類,實(shí)現(xiàn)了在抽象命令類中聲明的方法延届,它對(duì)應(yīng)具體的接收者對(duì)象剪勿,將接收者對(duì)象的動(dòng)作綁定其中。在實(shí)現(xiàn)execute()方法時(shí)方庭,將調(diào)用接收者對(duì)象的相關(guān)操作(Action)厕吉。
● Invoker(調(diào)用者):調(diào)用者即請(qǐng)求發(fā)送者,它通過命令對(duì)象來執(zhí)行請(qǐng)求械念。一個(gè)調(diào)用者并不需要在設(shè)計(jì)時(shí)確定其接收者头朱,因此它只與抽象命令類之間存在關(guān)聯(lián)關(guān)系。在程序運(yùn)行時(shí)可以將一個(gè)具體命令對(duì)象注入其中龄减,再調(diào)用具體命令對(duì)象的execute()方法项钮,從而實(shí)現(xiàn)間接調(diào)用請(qǐng)求接收者的相關(guān)操作。
● Receiver(接收者):接收者執(zhí)行與請(qǐng)求相關(guān)的操作希停,它具體實(shí)現(xiàn)對(duì)請(qǐng)求的業(yè)務(wù)處理烁巫。
結(jié)構(gòu)圖
時(shí)序圖
案例
這里就用電燈的開關(guān)作為案例
接收者接口
public interface Receiver {
void action();
}
電燈接收者類
有個(gè)flag表示電燈狀態(tài)是否是開啟還是關(guān)閉
public class LightReceiver implements Receiver{
private boolean flag = false;
@Override
public void action() {
if (flag) {
System.out.println("燈現(xiàn)在是開著的");
} else {
System.out.println("燈已經(jīng)關(guān)了");
}
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
命令接口
public interface Command {
void execute();
}
電燈命令類
public class LightCommand implements Command{
private LightReceiver lightReceiver;
public LightCommand(LightReceiver lightReceiver) {
super();
this.lightReceiver = lightReceiver;
}
@Override
public void execute() {
boolean flag = lightReceiver.isFlag() ? false : true;
lightReceiver.setFlag(flag);
lightReceiver.action();
}
}
開關(guān)類
public class SwitchInvoker {
private Command command;
public SwitchInvoker(Command command) {
this.command = command;
}
public void executeCommand(){
command.execute();
}
}
測試類
public class Client {
public static void main(String[] args) {
Command command = new LightCommand(new LightReceiver());
SwitchInvoker invoker = new SwitchInvoker(command);
for (int i = 0; i < 6; i++) {
invoker.executeCommand();
}
}
}
測試結(jié)果
總結(jié)
--
使用命令模式可以降低了系統(tǒng)耦合度,也比較容易擴(kuò)展脖苏,但是也可能會(huì)導(dǎo)致某些系統(tǒng)有過多的具體命令類程拭。
在碰到需要對(duì)行為進(jìn)行"記錄、撤銷/重做棍潘、事務(wù)"等處理時(shí)恃鞋,或者系統(tǒng)需要將請(qǐng)求調(diào)用者和請(qǐng)求接收者解耦,使得調(diào)用者和接收者不直接交互亦歉,又或者系統(tǒng)需要在不同的時(shí)間指定請(qǐng)求恤浪、請(qǐng)求排隊(duì)和執(zhí)行請(qǐng)求時(shí)就可以使用命令模式。