將一個(gè)請(qǐng)求封裝為對(duì)象,從而使你可以用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化;對(duì)請(qǐng)求排隊(duì)或記錄請(qǐng)求日志,以及支持可撤銷的操作
這里寫圖片描述
invoker中包含一系列命令,客戶端通過調(diào)用invoker來使得多條命令封裝在一起被執(zhí)行,方便回滾以及事務(wù)處理
命令模式的優(yōu)點(diǎn)
首先,命令模式的封裝性很好:每個(gè)命令都被封裝起來,對(duì)于客戶端來說,需要什么功能就去調(diào)用相應(yīng)的命令,而無需知道命令具體是怎么執(zhí)行的。比如有一組文件操作的命令:新建文件、復(fù)制文件、刪除文件。如果把這三個(gè)操作都封裝成一個(gè)命令類,客戶端只需要知道有這三個(gè)命令類即可,至于命令類中封裝好的邏輯,客戶端則無需知道。
其次,命令模式的擴(kuò)展性很好,在命令模式中,在接收者類中一般會(huì)對(duì)操作進(jìn)行最基本的封裝,命令類則通過對(duì)這些基本的操作進(jìn)行二次封裝,當(dāng)增加新命令的時(shí)候,對(duì)命令類的編寫一般不是從零開始的,有大量的接收者類可供調(diào)用,也有大量的命令類可供調(diào)用,代碼的復(fù)用性很好。比如,文件的操作中,我們需要增加一個(gè)剪切文件的命令,則只需要把復(fù)制文件和刪除文件這兩個(gè)命令組合一下就行了,非常方便。
命令模式的缺點(diǎn)
命令如果很多,開發(fā)起來就要頭疼了。特別是很多簡(jiǎn)單的命令,實(shí)現(xiàn)起來就幾行代碼的事,而使用命令模式的話,不用管命令多簡(jiǎn)單,都需要寫一個(gè)命令類來封裝。
命令模式的適用場(chǎng)景
對(duì)于大多數(shù)請(qǐng)求-響應(yīng)模式的功能,比較適合使用命令模式,正如命令模式定義說的那樣,命令模式對(duì)實(shí)現(xiàn)記錄日志、撤銷操作等功能比較方便。
代碼
Main
public class Main {
public static void main(String[] args) {
TV tv=new TV();
CommandOn on=new CommandOn(tv);
CommandOff off=new CommandOff(tv);
CommandChange change=new CommandChange(tv, 3);
Control c=new Control(on, off, change);
c.trunOn();
c.turnOff();
c.changeChanel();
}
}
interface:Command
public interface Command {
public void execute();
}
imp:TV
public class TV {
public int chanel=0;
public void trunOn(){
System.out.println("trun on");
}
public void trunOff(){
System.out.println("trun off");
}
public void changeChanel(int chanel){
this.chanel=chanel;
System.out.println("the chanel is "+this.chanel);
}
}
imp:CommandOn
public class CommandOn implements Command {
private TV tv=null;
public CommandOn(TV tv){
this.tv=tv;
}
@Override
public void execute() {
tv.trunOn();
}
}
imp:CommandOff
public class CommandOff implements Command {
private TV tv=null;
public CommandOff(TV tv){
this.tv=tv;
}
@Override
public void execute() {
this.tv.trunOff();
}
}
imp:CommandChange
public class CommandChange implements Command {
private TV tv=null;
private int chanel;
public CommandChange(TV tv,int chanel){
this.tv=tv;
this.chanel=chanel;
}
@Override
public void execute() {
this.tv.changeChanel(this.chanel);
}
}
imp:Control
public class Control {
private Command commandOn,commandOff,changeChanel;
public Control(Command on,Command off,Command change){
this.commandOn=on;
this.commandOff=off;
this.changeChanel=change;
}
public void trunOn(){
this.commandOn.execute();
}
public void turnOff(){
this.commandOff.execute();
}
public void changeChanel(){
this.changeChanel.execute();
}
}