指令模式是行为设计模式之一。指令设计模式用于在请求-响应模型中实现松散耦合。
指令模式
在指令模式中,请求被发送到
invoker
,invoker将其传递给封装的command
对象。Command对象将请求传递给Receiver
的适当方法以执行特定的操作。客户端程序创建接收器对象,然后将其附加到指令上。然后创建调用者对象并附加指令对象以执行操作。现在,当客户端程序执行操作时,它根据指令和接收器对象进行处理。
指令设计模式示例
我們將看一個實際情境,了解如何實現命令模式。假設我們想要提供一個檔案系統實用程式,具有開啟、寫入和關閉檔案的方法。這個檔案系統實用程式應該支援多個作業系統,如Windows和Unix。為了實現我們的檔案系統實用程式,首先我們需要創建接收器類別,這些類別將實際執行所有工作。由於我們使用Java中的介面,我們可以擁有FileSystemReceiver
介面及其實現類別,以支援不同的作業系統風格,如Windows、Unix、Solaris等。
命令模式接收器類別
package com.journaldev.design.command;
public interface FileSystemReceiver {
void openFile();
void writeFile();
void closeFile();
}
FileSystemReceiver介面定義了實現類別的契約。為了簡單起見,我創建了兩種接收器類別的變體,以配合Unix和Windows系統。
package com.journaldev.design.command;
public class UnixFileSystemReceiver implements FileSystemReceiver {
@Override
public void openFile() {
System.out.println("Opening file in unix OS");
}
@Override
public void writeFile() {
System.out.println("Writing file in unix OS");
}
@Override
public void closeFile() {
System.out.println("Closing file in unix OS");
}
}
package com.journaldev.design.command;
public class WindowsFileSystemReceiver implements FileSystemReceiver {
@Override
public void openFile() {
System.out.println("Opening file in Windows OS");
}
@Override
public void writeFile() {
System.out.println("Writing file in Windows OS");
}
@Override
public void closeFile() {
System.out.println("Closing file in Windows OS");
}
}
您是否注意到了Override註釋,如果您想知道為什麼使用它,請閱讀Java註釋和覆寫註釋的好處。現在我們的接收器類別已經準備好了,我們可以繼續實現我們的命令類別。
命令模式界面與實現
我們可以使用界面或抽象類來創建我們的基本命令,這是一個設計決策,取決於您的需求。我們選擇使用界面,因為我們沒有任何默認的實現。
package com.journaldev.design.command;
public interface Command {
void execute();
}
現在我們需要為接收器執行的所有不同類型的操作創建實現。由於我們有三個操作,我們將創建三個命令實現。每個命令實現將將請求轉發到接收器的適當方法。
package com.journaldev.design.command;
public class OpenFileCommand implements Command {
private FileSystemReceiver fileSystem;
public OpenFileCommand(FileSystemReceiver fs){
this.fileSystem=fs;
}
@Override
public void execute() {
//open命令正在將請求轉發到openFile方法
this.fileSystem.openFile();
}
}
package com.journaldev.design.command;
public class CloseFileCommand implements Command {
private FileSystemReceiver fileSystem;
public CloseFileCommand(FileSystemReceiver fs){
this.fileSystem=fs;
}
@Override
public void execute() {
this.fileSystem.closeFile();
}
}
package com.journaldev.design.command;
public class WriteFileCommand implements Command {
private FileSystemReceiver fileSystem;
public WriteFileCommand(FileSystemReceiver fs){
this.fileSystem=fs;
}
@Override
public void execute() {
this.fileSystem.writeFile();
}
}
現在我們有了接收器和命令實現,所以我們可以繼續實現調用者類。
命令模式調用者類
調用者是一個簡單的類,封裝了命令並將請求傳遞給命令對象以處理它。
package com.journaldev.design.command;
public class FileInvoker {
public Command command;
public FileInvoker(Command c){
this.command=c;
}
public void execute(){
this.command.execute();
}
}
我們的文件系統實用程序實現已經就緒,我們可以開始編寫一個簡單的命令模式客戶端程序。但在此之前,我將提供一個實用方法以創建適當的 FileSystemReceiver
對象。由於我們可以使用 System class 來獲取操作系統信息,因此我們將使用這個,否則我們可以使用 Factory pattern 根據輸入返回適當的類型。
package com.journaldev.design.command;
public class FileSystemReceiverUtil {
public static FileSystemReceiver getUnderlyingFileSystem(){
String osName = System.getProperty("os.name");
System.out.println("Underlying OS is:"+osName);
if(osName.contains("Windows")){
return new WindowsFileSystemReceiver();
}else{
return new UnixFileSystemReceiver();
}
}
}
現在,讓我們創建一個使用我們的文件系統實用程序的命令模式示例客戶端程序。
package com.journaldev.design.command;
public class FileSystemClient {
public static void main(String[] args) {
//創建接收器對象
FileSystemReceiver fs = FileSystemReceiverUtil.getUnderlyingFileSystem();
//創建命令並與接收器關聯
OpenFileCommand openFileCommand = new OpenFileCommand(fs);
//創建調用者並與命令關聯
FileInvoker file = new FileInvoker(openFileCommand);
//在調用者對象上執行操作
file.execute();
WriteFileCommand writeFileCommand = new WriteFileCommand(fs);
file = new FileInvoker(writeFileCommand);
file.execute();
CloseFileCommand closeFileCommand = new CloseFileCommand(fs);
file = new FileInvoker(closeFileCommand);
file.execute();
}
}
請注意,客戶端負責創建適當類型的命令對象。例如,如果要編寫文件,您不應該創建 CloseFileCommand
對象。客戶端程序還負責將接收器附加到命令,然後將命令附加到調用者類。上述命令模式示例程序的輸出為:
Underlying OS is:Mac OS X
Opening file in unix OS
Writing file in unix OS
Closing file in unix OS
Command Pattern 類圖
命令模式的重要點
- 命令是命令設計模式的核心,定義了實現的契約。
- 接收器實現與命令實現分開。
- 命令實現類選擇在接收器對象上調用的方法,對於接收器中的每個方法,都將有一個命令實現。它作為接收器和操作方法之間的橋樑。
- 調用者類只是將客戶端的請求轉發給命令對象。
- 客戶端負責實例化適當的命令和接收器實現,然後將它們關聯在一起。
- 客戶端還負責實例化調用者對象並將命令對象與其關聯起來並執行操作方法。
- 命令設計模式很容易擴展,我們可以在接收器中添加新的操作方法並創建新的命令實現,而不必更改客戶端代碼。
- 命令設計模式的缺點是,代碼會因為大量的操作方法和眾多關聯而變得龐大和混亂。
命令设计模式 JDK 示例
Runnable 接口(java.lang.Runnable)和 Swing Action(javax.swing.Action)使用命令模式。
Source:
https://www.digitalocean.com/community/tutorials/command-design-pattern