設(shè)計(jì)模式之命令模式(Command Pattern)

設(shè)計(jì)模式中有六大原則和二十三設(shè)計(jì)模式。
其中六大原則分別為:?jiǎn)我宦氊?zé)原則、開(kāi)閉原則、里氏替換原則、依賴(lài)倒置原則、接口隔離原則、迪米特原則。
二十三設(shè)計(jì)模式:?jiǎn)卫J?、Builder 模式、原型模式、工廠(chǎng)方法模式、抽象工廠(chǎng)模式、策略模式、狀態(tài)模式、責(zé)任鏈模式、解釋器模式、命令模式、觀察者模式、備忘錄模式、迭代器模式、模版方法模式、訪(fǎng)問(wèn)者模式、中介模式、代理模式、組合模式、適配器模式、裝飾模式、享元模式、外觀模式、橋接模式。

命令模式,看這個(gè)名字就知道它是以命令為終極目標(biāo),比如開(kāi)機(jī)命令、關(guān)機(jī)命令等。
命令模式相對(duì)于其他設(shè)計(jì)模式來(lái)說(shuō),它并沒(méi)有那么多的條條框框,它不是一個(gè)“規(guī)矩”的模式,它比其他模式更加靈活多變。

定義

將一個(gè)請(qǐng)求封裝成一個(gè)對(duì)象,從而讓用戶(hù)使用不同的請(qǐng)求把客戶(hù)端參數(shù)化;對(duì)請(qǐng)求排隊(duì)或者記錄請(qǐng)求日志,以及支持可撤銷(xiāo)的操作。

使用場(chǎng)景

認(rèn)為是命令的地方都可以使用命令模式。

  • 系統(tǒng)需要將請(qǐng)求調(diào)用者和請(qǐng)求接收者解耦,使得調(diào)用者和接收者不直接交互
  • 系統(tǒng)需要在不同的時(shí)間指定請(qǐng)求、將請(qǐng)求排隊(duì)和執(zhí)行請(qǐng)求
  • 系統(tǒng)需要支持命令的撤銷(xiāo)(Undo)操作和恢復(fù)(Redo)操作
  • 系統(tǒng)需要將一組操作組合在一起,即支持宏命令

優(yōu)缺點(diǎn)

優(yōu)點(diǎn)

  • 降低耦合度
  • 靈活性更高,新的命令可以很容易加到系統(tǒng)中
  • 實(shí)現(xiàn)簡(jiǎn)單,可以比較容易的設(shè)計(jì)一個(gè)命令
  • 調(diào)用同一方法實(shí)現(xiàn)不同功能

缺點(diǎn)

  • 類(lèi)爆炸,使用命令模式可能會(huì)導(dǎo)致某些系統(tǒng)有過(guò)多的具體命令類(lèi)

UML圖

命令模式.png
  • Receiver:接收者角色。負(fù)責(zé)具體實(shí)施或執(zhí)行一個(gè)請(qǐng)求,真正執(zhí)行命令的對(duì)象。任何類(lèi)都可能成為一個(gè)接收者,只要它能夠?qū)崿F(xiàn)命令要求實(shí)現(xiàn)的相應(yīng)功能
  • Command:命令角色。定義所有具體命令類(lèi)的抽象接口
  • ConcreteCommand:具體命令角色。命令接口實(shí)現(xiàn)對(duì)象,是“虛”的實(shí)現(xiàn);通常會(huì)持有接收者,并調(diào)用接收者的功能來(lái)完成命令要執(zhí)行的操作
  • Invoker:請(qǐng)求者角色。要求命令對(duì)象執(zhí)行請(qǐng)求,通常會(huì)持有命令對(duì)象,可以持有很多的命令對(duì)象。這個(gè)是客戶(hù)端真正觸發(fā)命令并要求命令執(zhí)行相應(yīng)操作的地方,也就是說(shuō)相當(dāng)于使用命令對(duì)象的入口

代碼實(shí)現(xiàn)

  • 接收者
/**
 * 接收者
 */
public class Receiver {
    // 執(zhí)行具體命令邏輯的方法
    public void action1(){
        System.out.println("執(zhí)行具體操作邏輯1");
    }
}
  • 命令角色
/**
 * 命令接口
 */
public interface Command {
    /**
     * 執(zhí)行命令
     */
    void execute();
}
  • 命令具體實(shí)現(xiàn)
/**
 * 具體命令角色
 */
public class ConcreteCommand1 implements Command {
    private Receiver receiver;

    public ConcreteCommand1(Receiver receiver) {
        this.receiver = receiver;
    }

    /**
     * 執(zhí)行命令
     */
    @Override
    public void execute() {
        // 調(diào)用接收者的相關(guān)方法來(lái)執(zhí)行具體邏輯
        receiver.action1();
    }
}
  • 請(qǐng)求者角色
/**
 * 請(qǐng)求者角色
 */
public class Invoker {
    private Command command1;
    
    /**
     * 執(zhí)行請(qǐng)求方法
     */
    public void action1(){
        // 調(diào)用具體命令對(duì)象的相關(guān)方法,執(zhí)行具體命令
        command1.execute();
    }

    public Command getCommand1() {
        return command1;
    }

    public void setCommand1(Command command1) {
        this.command1 = command1;
    }
}
  • 執(zhí)行
public static void main(String[] args) {
    // 定義接收者(執(zhí)行具體邏輯)
    Receiver receiver =new Receiver();
    // 根據(jù)接收者構(gòu)造具體命令對(duì)象
    Command command1 = new ConcreteCommand1(receiver);
    Command command2 = new ConcreteCommand2(receiver);
    // 根據(jù)命令對(duì)象構(gòu)造請(qǐng)求對(duì)象
    Invoker invoker = new Invoker();
    invoker.setCommand1(command1);
    invoker.setCommand2(command2);
    // 發(fā)送命令請(qǐng)求
    invoker.action1();
    invoker.action2();
}
  • 結(jié)果
執(zhí)行具體操作邏輯1
執(zhí)行具體操作邏輯2

總結(jié)

命令模式看起來(lái)和策略模式很像(策略模式好像和所有模式都好像??♂?),
Command模式用于從需要完成的操作中創(chuàng)建一個(gè)對(duì)象 - 獲取操作及其參數(shù)并將它們包裝在要記錄的對(duì)象中,保留用于撤消隨著時(shí)間的推移,將會(huì)有大量不同的Command對(duì)象通過(guò)系統(tǒng)中的給定點(diǎn),并且Command對(duì)象將包含描述所請(qǐng)求操作的不同參數(shù)。
策略模式則用于指定如何應(yīng)該完成的事情,并插入更大的對(duì)象或方法以提供特定的算法。排序策略可能是合并排序,可能是插入排序,也可能是更復(fù)雜的事情,如果列表大于某個(gè)最小大小,則僅使用合并排序。策略對(duì)象很少受到Command對(duì)象的大規(guī)?;靵y,而是經(jīng)常用于配置或調(diào)優(yōu)目的。
這兩種模式都涉及將包含它們的原始類(lèi)中的單個(gè)操作的代碼和可能的參數(shù)分解為另一個(gè)對(duì)象以提供獨(dú)立的可變性。不同之處在于實(shí)踐中遇到的用例以及每種模式背后的意圖。

DEMO
參考
《Android 源碼設(shè)計(jì)模式解析與實(shí)踐》
策略模式和命令模式的不同

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容