8.6命令模式
8.6.1概念
? 命令模式允許將請求封裝成一個對象(命令對象,包含執(zhí)行操作所需地所有信息),并將命令對象按照一定的順序存儲在隊列中,然后再逐一調用執(zhí)行,這些命令可以支持反向操作,進行撤銷和重做。這樣發(fā)送者就只需要觸發(fā)命令就可以完成操作,不需要知道接受者的具體操作,從而實現兩者間的解耦
8.6.2場景
? 在餐飲業(yè)中,命令模式可以用于實現訂單的處理流程。例如在餐廳中,當我們在客戶端或者小程序上進行點單,客戶端 / 小程序會將我們在上面下的訂單請求封裝成為一個對象,通過發(fā)送命令給后廚的工作人員上,而他們就會根據我們下的具體訂單進行菜品備菜、菜品制作、菜品上菜等一系列操作。
8.6.3優(yōu)勢 / 劣勢
- 降低系統(tǒng)的耦合度:將請求的發(fā)送者和接收者解耦
- 提高系統(tǒng)擴展性:可以方便地擴展新的命令和接收者,提高系統(tǒng)的擴展力
- 增加請求隊列:可以很容易地增加一個請求隊列,以便在需要時處理或延遲處理請求
- 支持撤銷操作:通過記錄一系列命令,可以很輕松地回溯并撤銷之前地操作
- 增加系統(tǒng)的復雜性:需要創(chuàng)建多個類和對象
- 執(zhí)行順序不保證:不能保證命令的執(zhí)行順序
8.6.4命令模式可分為
- 命令接口Command:接口或抽象類,定義執(zhí)行操作的接口
- 具體命令類ConcreteCommand:實現命令接口,執(zhí)行具體操作,在調用execute方法時"接收者對象"根據命令完成具體的任務,比如遙控器中的"開機","關機"命令
- 接收者類Receiver:接受并執(zhí)行命令的對象,可以是任何對象,遙控器可以控制空調,也可以控制電視機,電視機和空調負責執(zhí)行具體操作,是接收者
- 調用者類Invoker:發(fā)起請求的對象,有一個將命令作為參數傳遞的方法。它不關心命令的具體實現,只負責調用命令對象的execute()方法來傳遞請求,在本例中,控制遙控器的"人"就是調用者
- 客戶端:創(chuàng)建具體的命令對象和接收者對象,然后將它們組裝起來
8.6.5命令模式
package com.technologystatck.designpattern.mode.command;
import java.util.*;
public class Commands {
public static void main(String[] args) {
Receiver receiver = new Receiver();
ConcreteCommand command = new ConcreteCommand(receiver);
new Invoker(command).executeCommand();
}
}
//定義執(zhí)行操作的接口,包含一個execute方法,有時還會包括unExecute方法,表示撤銷命令
interface Command{
//執(zhí)行方法
void execute();
//撤銷方法
void undo();
}
//實現命令接口,執(zhí)行具體的操作
class ConcreteCommand implements Command{
//接收者對象
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.action();
}
@Override
public void undo() {
receiver.unAction();
}
}
//定義接受者類,知道如何實施與執(zhí)行一個請求相關的操作
class Receiver{
public void action(){
//執(zhí)行操作
}
public void unAction(){
//撤銷操作
}
}
//定義調用者類,調用命令對象執(zhí)行請求
class Invoker{
private Command command;
public Invoker(Command command) {
this.command = command;
}
public void executeCommand(){
command.execute();
}
}
//調用者類可以維護一個命令隊列或者撤銷棧,以支持批處理和撤銷命令
class Invoker{
//命令隊列
private Queue<Command> commandQueue;
//撤銷棧
private Stack<Command> undoStack;
public Invoker(Queue<Command> commandQueue, Stack<Command> undoStack) {
this.commandQueue = new LinkedList<>();
this.undoStack = new Stack<>();
}
//設置命令并執(zhí)行
public void setAndExecuteCommand(Command command){
command.execute();
commandQueue.offer(command);
undoStack.push(command);
}
//撤銷上一個命令
public void undoLastCommand(){
if(!undoStack.isEmpty()){
Command lastCommand = undoStack.pop();
//命令類實現undo方法
lastCommand.undo();
commandQueue.remove(lastCommand);
}else{
System.out.println("No command to undo.");
}
}
//執(zhí)行命令隊列中的所有命令
public void executeCommandsInQueue(){
for (Command command : commandQueue) {
command.execute();
}
}
}
8.6.6實戰(zhàn)
8.6.6.1題目描述
小明去奶茶店買奶茶,他可以通過在自助點餐機上來點不同的飲品,請你使用命令模式設計一個程序,模擬這個自助點餐系統(tǒng)的功能。文章來源:http://www.zghlxwxcb.cn/news/detail-819032.html
8.6.6.2輸入描述
- 第一行是一個整數 n(1 ≤ n ≤ 100),表示點單的數量。
- 接下來的 n 行,每行包含一個字符串,表示點餐的飲品名稱。
8.6.6.3輸出描述
輸出執(zhí)行完所有點單后的制作情況,每行輸出一種飲品的制作情況。如果制作完成,輸出 “XXX is ready!”,其中 XXX 表示飲品名稱。文章來源地址http://www.zghlxwxcb.cn/news/detail-819032.html
8.6.6.4代碼
package com.technologystatck.designpattern.mode.command;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//創(chuàng)建接收者和命令對象
DrinkMaker drinkMaker = new DrinkMaker();
//讀取命令數量
int nums=scanner.nextInt();
scanner.nextLine();
while(nums-- > 0){
//讀取命令
String drinkName=scanner.next();
//創(chuàng)建命令對象
OrderCommand command = new OrderCommand(drinkName, drinkMaker);
//執(zhí)行命令
OrderMachine orderMachine = new OrderMachine();
orderMachine.setCommand(command);
orderMachine.executeOrder();
}
scanner.close();
}
}
//定義執(zhí)行操作的命令訂單接口
interface Command{
void execute();
}
//定義具體命令類實現點餐
class OrderCommand implements Command{
//飲料名稱
private String drinkName;
//具體的飲料制作者
private DrinkMaker drinkMaker;
public OrderCommand(String drinkName, DrinkMaker drinkMaker) {
this.drinkName = drinkName;
this.drinkMaker = drinkMaker;
}
@Override
public void execute() {
drinkMaker.makeDrink(drinkName);
}
}
//接收者類-制作飲料
class DrinkMaker{
public void makeDrink(String drinkName){
System.out.println(drinkName+" is ready!");
}
}
//調用者類-點餐機
class OrderMachine{
private Command command;
public void setCommand(Command command) {
this.command = command;
}
//執(zhí)行下單方法
public void executeOrder(){
command.execute();
}
}
8.6.7總結
- 優(yōu)點:方便擴展新的命令和接收者,還可以撤銷操作,增加系統(tǒng)的靈活性和可維護性
- 總結:將請求封裝成一個對象,通過具體命令類、調用者、接收者以此來完成相關操作
- 場景:適用于需要實現撤銷操作,需要保證事務一致性等場景
到了這里,關于笨蛋學設計模式行為型模式-命令模式【19】的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!