一、命令模式介紹
命令模式:將一個請求封裝爲一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可撤銷的操作。
說白了,就是將一系列的請求命令封裝起來,不直接調用真正執行者的方法,這樣比較好擴展。
命令模式UML圖:
Command(抽象命令類):抽象出命令對象,可以根據不同的命令類型,寫出不同的實現類。
ConcreteCommand(具體命令類):實現了抽象命令對象的具體實現。
Invoker(調用者/請求者):請求的發送者,它通過命令對象來執行請求。一個調用者並不需要在設計時確定其接收者,因此它只與抽象命令來之間存在關聯。在程序運行時,將調用命令對象的execute() ,間接調用接收者的相關操作。
Receiver(接收者):接收者執行與請求相關的操作,真正執行命令的對象。具體實現對請求的業務處理。任何類都可能作爲一個接收者。
Client(客戶端):在客戶類中需要創建調用者對象,具體命令類對象,在創建具體命令對象時指定對應的接收者。發送者和接收者之間沒有之間關係,都通過命令對象來調用。
二、命令模式代碼實現
首先定義一個命令的接收者,也就是到最後真正執行命令的那個對象。
//接收者:真正執行命令的對象
public class Receiver {
public void action(){
System.out.println("命令執行了.......");
}
}
然後定義抽象命令和抽象命令的具體實現,具體命令類中需要持有真正執行命令的那個對象。
//抽象命令類:抽象的命令,可以根據不同類型的命令寫出不同的實現
public interface Command {
//調用命令,還可以定義其他方法,比如撤銷undo
void execute();
}
//具體命令類
class ConcreteCommand implements Command{
private Receiver receiver;//持有真正執行命令對象的引用,可以使用容器持有多個receiver
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
//調用接收者執行命令的方法,調用前後可以做相關處理
receiver.action();
}
}
接下來就可以定義命令的發起者了,發起者需要持有一個命令對象,以便來發起命令。
//請求者/調用者:發起執行命令請求的對象
public class Invoker {
private Command command;//持有命令對象的引用,可以使用容器持有多個command
public Invoker(Command command) {
this.command = command;
}
public void call(){
//請求者調用命令對象執行命令的那個execute方法,調用前後可以做相關處理
command.execute();
}
}
客戶端測試:客戶端
public static void main(String[] args) {
//通過請求者(invoker)調用命令對象(command),命令對象中調用了命令具體執行者(Receiver)
Command command = new ConcreteCommand(new Receiver());
Invoker invoker = new Invoker(command);
invoker.call();
}
結果打印:命令執行了.......
代碼的UML圖如下:
三、應用場景
Struts2中action中的調用過程中存在命令模式。
數據庫中的事務機制的底層實現。
命令的撤銷和恢復:增加相應的撤銷和恢復命令的方法(比如數據庫中的事務回滾)。