命令模式是一種行為模式。
命令模式的定義
命令模式是一個高內聚的模式,將一個請求封裝成一個物件,從而讓你使用不同的請求把客戶端引數化,對請求排隊或者記錄日誌,可以提供命令的撤銷和恢復功能。命令模式的核心在於引入了命令類,通過命令類來降低傳送者和接收者的耦合度,請求傳送者只需指定一個命令物件,再通過命令物件來呼叫請求接收者的處理方法。
命令模式可以將請求傳送者和接收者完全解耦,傳送者與接收者之間沒有直接引用關係,傳送請求的物件只需要知道如何傳送請求,而不必知道如何完成請求。
命令模式的結構
命令模式包含如下角色:
-
Receiver接收者角色
命令接收者模式,命令傳遞到這裡執行對應的操作。 -
Command命令角色
需要執行的命令都在這裡宣告 -
Invoker呼叫者角色
接收到命令,並執行命令,也就是命令的發動者和呼叫者
命令模式的實現
抽象Command類。
public abstract class Command {
public abstract void execute();
}
複製程式碼
呼叫者Invoker類。
public class Invoker {
private Command command;
//構造注入
public Invoker(Command command) {
this.command = command;
}
//設值注入
public void setCommand(Command command) {
this.command = command;
}
//業務方法,用於呼叫命令類的execute()方法
public void call() {
command.execute();
}
}
複製程式碼
具體Command類,設定對應的接收者。
public class ConcreteCommand extends Command {
private Receiver receiver; //維持一個對請求接收者物件的引用
public ConcreteCommand(Receiver receiver) {
super();
this.receiver = receiver;
}
public void execute() {
receiver.action(); //呼叫請求接收者的業務處理方法action()
}
}
複製程式碼
抽象接收者。
public abstract class Receiver {
public abstract void action();
}
複製程式碼
第一個接收者。
public class ConcreteReceiver extends Receiver{
@Override
public void action() {
System.out.println("ConcreteReceiver receives the command!");
}
}
複製程式碼
第二個接收者。
public class ConcreteReceiver2 extends Receiver{
@Override
public void action() {
System.out.println("ConcreteReceiver2 receives the command!");
}
}
複製程式碼
測試類,建立了連個接收者,分別傳送指令。
public class Client {
public static void main(String[] args) {
Receiver receiver1 = new ConcreteReceiver();
Command command1 = new ConcreteCommand(receiver1);
Invoker invoker = new Invoker();
invoker.setCommand(command1);
invoker.call();
Receiver receiver2 = new ConcreteReceiver2();
Command command2 = new ConcreteCommand(receiver2);
invoker.setCommand(command2);
invoker.call();
}
}
複製程式碼
總結
命令模式的本質是對請求進行封裝,一個請求對應於一個命令,將發出命令的責任和執行命令的責任分割開。每一個命令都是一個操作:請求的一方發出請求要求執行一個操作;接收的一方收到請求,並執行相應的操作。命令模式允許請求的一方和接收的一方獨立開來,使得請求的一方不必知道接收請求的一方的介面,更不必知道請求如何被接收、操作是否被執行、何時被執行,以及是怎麼被執行的。命令模式的關鍵在於引入了抽象命令類,請求傳送者針對抽象命令類程式設計,只有實現了抽象命令類的具體命令才與請求接收者相關聯。
命令模式的優點是:
-
類間解藕
呼叫者角色與接受者角色之間沒有任何依賴關係,呼叫者實現功能時只需要呼叫Command抽象類的execute方法就可以,不需要知道到底是哪個接收者執行。 -
可擴充套件性
Command子類可以非常容易的擴充套件,而呼叫者Invoker和高層次的模組Client不產生嚴重的程式碼藕合
其缺點是造成了類膨脹,如果有多個子命令對應多個Command子類,比較繁瑣。