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

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

