Java設(shè)計模式之命令模式CommandPattern詳解
概念
命令模式:把一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數(shù)化;對請求排隊或記錄請求日志,以及支持可撤銷的操作。
在軟件系統(tǒng)中,“行為請求者”與“行為實現(xiàn)者”通常呈現(xiàn)一種“緊耦合”。但在某些場合,比如要對行為進行“記錄、撤銷/重做、事務(wù)”等處理,這種無法抵御變化的緊耦合是不合適的。在這種情況下,如何將“行為請求者”與“行為實現(xiàn)者”解耦?將一組行為抽象為對象,實現(xiàn)二者之間的松耦合。這就是命令模式(Command Pattern)
UML模式結(jié)構(gòu)分析

Command接口:
定義命令的接口,聲明執(zhí)行的方法execute()。
ConcreteCommand子類:
命令接口實現(xiàn)對象,不同命令對應(yīng)不同子類。通常具體命令類會持有接受者引用,并調(diào)用接收者的功能來完成命令要執(zhí)行 的操作。
Receiver類:
接收者,真正執(zhí)行命令的對象。任何類都可能成為一個接收者,只要它能夠?qū)崿F(xiàn)命令要求實現(xiàn)的相應(yīng)功能。
Invoker類:
要求命令對象執(zhí)行請求,通常會持有命令對象,可以持有很多的命令對象。這個是客戶端真正觸發(fā)命令并要求命令執(zhí)行相應(yīng)操作的地方,也就是說相當于使用命令對象的入口。
Client類:
創(chuàng)建具體的命令對象,并且設(shè)置命令對象的接收者。注意這個不是我們常規(guī)意義上的客戶端,而是在組裝命令對象和接收者,或許,把這個Client稱為裝配者會更好理解,因為真正使用命令的客戶端是從Invoker來觸發(fā)執(zhí)行。
模式協(xié)作
- Client創(chuàng)建一個ConcreteCommand對象并指定他的Receiver對象
- 某個Invoker對象存儲該ConcreteCommand對象
- 該Invoker通過調(diào)用Command對象的Execute操作來提交一個請求。若該命令是可撤銷的,ConcreteCommand就在執(zhí)行Execute操作之前存儲當前狀態(tài)以用于取消該命令
- ConcreteCommand對象對調(diào)用它的Receiver的一些操作以執(zhí)行該請求
實例解析
電視機是請求的接收者(Receiver),遙控器是請求的發(fā)送者(Invoker),遙控器上有一些按鈕,不同的按鈕對應(yīng)電視機的不同操作(ConcreteCommand)。抽象命令角色由一個命令接口(Command)來扮演,有三個具體的命令類實現(xiàn)了抽象命令接口,這三個具體命令類分別代表三種操作:打開電視機、關(guān)閉電視機和切換頻道。顯然,電視機遙控器就是一個典型的命令模式應(yīng)用實例。
接收者Television:
package commandpattern;
public class Television {
private int channel;
public void turnOn() {
System.out.println("The televison is on.");
}
public void turnOff() {
System.out.println("The television is off.");
}
public void changeChannel(int channel) {
this.channel = channel;
System.out.println("Now televison channel is " + channel);
}
}命令接口:
package commandpattern;
public interface Command {
public void execute();
}具體命令——打開電視機CommandOn:
package commandpattern;
public class CommandOn implements Command {
private Television television;
public CommandOn(Television television) {
this.television = television;
}
@Override
public void execute() {
// TODO Auto-generated method stub
television.turnOn();
}
}具體命令——切換頻道CommandChange:
package commandpattern;
public class CommandChange implements Command {
private Television television;
private int channel;
public CommandChange(Television television,int channel) {
this.channel = channel;
this.television = television;
}
@Override
public void execute() {
// TODO Auto-generated method stub
television.changeChannel(channel);
}
}具體命令——關(guān)閉電視機CommandOff:
package commandpattern;
public class CommandOff implements Command {
private Television television;
public CommandOff(Television television) {
this.television = television;
}
@Override
public void execute() {
// TODO Auto-generated method stub
television.turnOff();
}
}命令發(fā)起人Invoker,這里就是遙控器Control類,它持有多種具體命令對象:
package commandpattern;
public class Control {
private Command onCommand, offCommand, changeCommand;
public Control(Command on, Command off, Command change) {
onCommand = on;
offCommand = off;
changeCommand = change;
}
public void turnOn() {
onCommand.execute();
}
public void turnOff() {
offCommand.execute();
}
public void changeChannel() {
changeCommand.execute();
}
}客戶端Client,創(chuàng)建接收者,創(chuàng)建具體命令持有接收者,創(chuàng)建命令發(fā)起人持有各種具體命令。
package commandpattern;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//命令接收者
Television television = new Television();
//命令
CommandOn on = new CommandOn(television);
CommandOff off = new CommandOff(television);
CommandChange change = new CommandChange(television, 4);
Control control = new Control(on, off, change);
//執(zhí)行命令
control.turnOn();
control.changeChannel();
control.turnOff();
}
}輸出:
The televison is on.
Now televison channel is 4
The television is off.
其實命令模式像很多設(shè)計模式一樣——通過在你的請求和處理之間加上了一個中間人的角色,來達到分離耦合的目的。通過對中間人角色的特殊設(shè)計來形成不同的模式。
當然命令模式就是一種特殊設(shè)計的結(jié)果。
優(yōu)點:
- 降低對象之間的耦合度。
- 新命令可以很容易地加入到系統(tǒng)中。
- 可以比較容易地設(shè)計一個組合命令。
- 調(diào)用同一方法實現(xiàn)不同功能。
缺點:
使用命令模式可能會導(dǎo)致某些系統(tǒng)有過多的具體命令類。因為針對每一個命令都需要設(shè)計一個具體命令類,因此某些系統(tǒng)可能需要大量具體命令類,這將影響命令模式的使用。
到此這篇關(guān)于Java設(shè)計模式之命令模式CommandPattern詳解的文章就介紹到這了,更多相關(guān)Java命令模式CommandPattern內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Ubuntu手動安裝JDK?17完整教程(.tar.gz?方式)
JDK是Java開發(fā)的核心組件之一,它包含了Java編譯器和Java運行時環(huán)境,以及其他開發(fā)工具和庫,這篇文章主要介紹了Ubuntu手動安裝JDK?17(.tar.gz?方式)的相關(guān)資料,需要的朋友可以參考下2026-02-02
基于SpringBoot創(chuàng)建Web頁面并熱更新的操作步驟
SpringBoot是一個用于快速開發(fā)單個微服務(wù)的框架,它基于 Spring 框架,簡化了Spring應(yīng)用的初始化過程和開發(fā)流程,本文給大家介紹了如何基于SpringBoot創(chuàng)建Web頁面并熱更新,文中通過圖文介紹的非常詳細,需要的朋友可以參考下2023-11-11
java讀取文件:char的ASCII碼值=65279,顯示是一個空字符的解決
這篇文章主要介紹了java讀取文件:char的ASCII碼值=65279,顯示是一個空字符的解決,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08
IDEA修改java文件后 不用重啟Tomcat服務(wù)便可實現(xiàn)自動更新
這篇文章主要介紹了IDEA修改java文件后 不用重啟Tomcat服務(wù)便可實現(xiàn)自動更新,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11
解決rocketmq-spring-boot-starter導(dǎo)致的多消費者實例重復(fù)消費問題
這篇文章主要介紹了解決rocketmq-spring-boot-starter導(dǎo)致的多消費者實例重復(fù)消費問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-06-06
Java?報錯?java.util.ConcurrentModificationException:?null?
這篇文章主要介紹了Java?報錯?java.util.ConcurrentModificationException:?null?的原因和解決方案,這個異常通常在多線程環(huán)境下出現(xiàn),意味著在迭代過程中,集合或者映射的結(jié)構(gòu)發(fā)生了變化,本文分享完美解決方案,需要的朋友可以參考下2023-07-07
Java如何將處理完異常之后的程序能夠從拋出異常的地點向下執(zhí)行?
今天小編就為大家分享一篇關(guān)于Java如何將處理完異常之后的程序能夠從拋出異常的地點向下執(zhí)行?,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-04-04
Springboot3自定義starter業(yè)務(wù)代碼
在Spring?Boot中,starter是一種特殊的依賴,它可以幫助開發(fā)人員快速引入和配置某個特定的功能模塊,這篇文章給大家介紹Springboot3自定義starter業(yè)務(wù)代碼的相關(guān)知識,感興趣的朋友跟隨小編一起看看吧2025-05-05

