Java設(shè)計(jì)模式之命令模式詳細(xì)解析
1、簡介
1.1、定義
命令模式:將請(qǐng)求封裝成對(duì)象,以便使用不同的請(qǐng)求、隊(duì)列或者日志來參數(shù)化其他對(duì)象。(同時(shí)也支持可撤銷的操作)
1.2、解決的問題
通常在系統(tǒng)設(shè)計(jì)中,行為請(qǐng)求者和行為實(shí)現(xiàn)者是緊耦合的關(guān)系。
而在一些特定的場景下,比如:需要對(duì)行為進(jìn)行記錄、撤銷或重做、事務(wù)等處理時(shí),需要將行為請(qǐng)求者和行為實(shí)現(xiàn)者分離開來,這時(shí)就可以用到命令模式。
1.3、模式結(jié)構(gòu)
- Command:定義命令的接口,聲明執(zhí)行的方法
- ConcreteCommand:命令接口實(shí)現(xiàn)對(duì)象,是“命令接口”的實(shí)現(xiàn);通常會(huì)持有接收者,并調(diào)用接收者的功能來完成命令要執(zhí)行的操作
- Receiver:接收者,真正執(zhí)行命令的對(duì)象。任何類都可能成為一個(gè)接收者,只要它能夠?qū)崿F(xiàn)命令要求實(shí)現(xiàn)的相應(yīng)功能
- Invoker:要求命令對(duì)象執(zhí)行請(qǐng)求,通常會(huì)持有命令對(duì)象,可以持有很多的命令對(duì)象。這個(gè)是客戶端真正觸發(fā)命令并要求命令執(zhí)行相應(yīng)操作的地方,也就是說相當(dāng)于使用命令對(duì)象的入口
- Client:創(chuàng)建具體的命令對(duì)象,并且設(shè)置命令對(duì)象的接收者。注意這個(gè)不是我們常規(guī)意義上的客戶端,而是在組裝命令對(duì)象和接收者,或許,把這個(gè)Client稱為裝配者會(huì)更好理解,因?yàn)檎嬲褂妹畹目蛻舳耸菑腎nvoker來觸發(fā)執(zhí)行
1.4、結(jié)構(gòu)類圖

1.5、運(yùn)作流程
- Client創(chuàng)建一個(gè)ConcreteCommand對(duì)象并指定他的Receiver對(duì)象
- 某個(gè)Invoker對(duì)象存儲(chǔ)該ConcreteCommand對(duì)象
- 該Invoker通過調(diào)用Command對(duì)象的Execute操作來提交一個(gè)請(qǐng)求。若該命令是可撤銷的,ConcreteCommand就在執(zhí)行Execute操作之前存儲(chǔ)當(dāng)前狀態(tài)以用于取消該命令
- ConcreteCommand對(duì)象對(duì)調(diào)用它的Receiver的一些操作以執(zhí)行該請(qǐng)求
2、示例Demo
2.1、Command
package com.jbp.designpattern.command;
/**
* @ClassName: Order
* @description: 命令接口 --- Command
* @author: JiangBeiPing
* @create: 2021-07-23 11:15
* @Version: 1.0
**/
public interface Order {
void execute();
}
2.2、ConcreteCommand
package com.jbp.designpattern.command;
/**
* @ClassName: BuyStock
* @description: 加庫存 --- ConcreteCommmand
* @author: JiangBeiPing
* @create: 2021-07-23 11:39
* @Version: 1.0
**/
public class BuyStock implements Order{
private Stock stock;
public BuyStock(Stock stock) {
this.stock = stock;
}
@Override
public void execute() {
stock.buy();
}
}
package com.jbp.designpattern.command;
/**
* @ClassName: SellStock
* @description: 清庫存 --- ConcreteCommmand
* @author: JiangBeiPing
* @create: 2021-07-23 11:41
* @Version: 1.0
**/
public class SellStock implements Order{
private Stock stock;
public SellStock(Stock stock) {
this.stock = stock;
}
@Override
public void execute() {
stock.sell();
}
}
2.3、Receiver
package com.jbp.designpattern.command;
/**
* @ClassName: Stock
* @description: 請(qǐng)求類 --- Receiver
* @author: JiangBeiPing
* @create: 2021-07-23 11:16
* @Version: 1.0
**/
public class Stock {
private String name = "庫存一號(hào)";
// 數(shù)量
private int quantity = 10;
public void buy(){
System.out.println("名字:" + name + ",數(shù)量:" + quantity);
}
public void sell(){
System.out.println("名字:" + name + ",數(shù)量:" + quantity);
}
}
2.4、Invoker
package com.jbp.designpattern.command;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName: Broker
* @description: 命令調(diào)用類 --- invoker
* @author: JiangBeiPing
* @create: 2021-07-23 11:43
* @Version: 1.0
**/
public class Broker {
private List<Order> orderList = new ArrayList<>();
// 加庫存
public void takeOrder(Order order){
orderList.add(order);
}
// 清庫存
public void placeOrders(){
for (Order order : orderList) {
order.execute();
}
orderList.clear();
}
}
2.5、Client
package com.jbp.designpattern.command;
/**
* @ClassName: test
* @description: 測試 --- Client
* @author: JiangBeiPing
* @create: 2021-07-23 11:50
* @Version: 1.0
**/
public class test {
public static void main(String[] args) {
Stock stock = new Stock();
BuyStock buyStock = new BuyStock(stock);
SellStock sellStock = new SellStock(stock);
Broker broker = new Broker();
broker.takeOrder(buyStock);
broker.takeOrder(sellStock);
broker.placeOrders();
}
}
3、優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
類間解耦:調(diào)用者角色與接收者角色之間沒有任何依賴關(guān)系可擴(kuò)展性:Command的子類具備高擴(kuò)展性可以比較容易地設(shè)計(jì)一個(gè)組合命令
缺點(diǎn)
Command的子類過多(如果有過多的命令,就會(huì)有過多的Command子類)
使用場景
隊(duì)列請(qǐng)求日志請(qǐng)求系統(tǒng)需要將一組操作組合在一起,即支持宏命令
到此這篇關(guān)于Java設(shè)計(jì)模式之命令模式詳細(xì)解析的文章就介紹到這了,更多相關(guān)Java命令模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot基礎(chǔ)學(xué)習(xí)之Mybatis操作中使用Redis做緩存詳解
這篇文章主要給大家介紹了關(guān)于Spring Boot基礎(chǔ)學(xué)習(xí)之Mybatis操作中使用Redis做緩存的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用spring boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧2018-11-11
MybatisPlus使用Mybatis的XML的動(dòng)態(tài)SQL的功能實(shí)現(xiàn)多表查詢
本文主要介紹了MybatisPlus使用Mybatis的XML的動(dòng)態(tài)SQL的功能實(shí)現(xiàn)多表查詢,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-11-11
java 方法重寫與權(quán)限修飾符以及多態(tài)和抽象類詳解概念和用法
重寫是子類對(duì)父類的允許訪問的方法的實(shí)現(xiàn)過程進(jìn)行重新編寫, 返回值和形參都不能改變。即外殼不變,核心重寫,權(quán)限修飾符用于控制被修飾變量、方法、類的可見范圍,說明了面向?qū)ο蟮姆庋b性,所以我們要適用他們盡可能的讓權(quán)限降到最低,從而安全性提高2021-10-10
SpringBoot同一接口多個(gè)實(shí)現(xiàn)類配置的實(shí)例詳解
這篇文章主要介紹了SpringBoot同一接口多個(gè)實(shí)現(xiàn)類配置的實(shí)例詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11
eclipse中沒有SERVER的解決辦法(超詳細(xì))
使用eclipse進(jìn)行tomcat配置時(shí),經(jīng)常會(huì)發(fā)現(xiàn)一個(gè)重要的問題就是打開eclipse之后沒有了server選項(xiàng),所以本給大家詳細(xì)介紹了eclipse中沒有SERVER的解決辦法,文中有詳細(xì)的圖文講解,需要的朋友可以參考下2023-12-12
java final 和instanceof 關(guān)鍵字的區(qū)別
這篇文章介紹了java final 和instanceof 關(guān)鍵字的區(qū)別,有需要的朋友可以參考一下2013-09-09
java高級(jí)應(yīng)用:線程池的全面講解(干貨)
這篇文章主要介紹了java高級(jí)應(yīng)用:線程池的全面講解(干貨),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-02-02

