首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

設計模式四人幫:命令模式深度解析與 Java 實作

     編輯:Java 相關知識

命令模式將「請求」封裝為物件,實現發送者與接收者解耦,支援佇列、日誌、撤銷/重做等進階功能。本文結合 GoF 定義、生活類比、UML 結構與 Java 完整範例,深入剖析此模式精髓。

模式意圖

將請求封裝為物件,使你能用不同請求參數化客戶端、將請求排隊或記錄日誌、支援可撤銷操作。

生活類比

老闆(Client)發出命令 → 秘書 跑腿傳遞 → 員工 執行實際工作。老闆不需知道誰執行、如何執行;員工不需知道命令來源。秘書負責傳遞、排隊、記錄。

UML 結構

命令模式類別圖

  • Command:介面,宣告 execute()
  • ConcreteCommand:綁定 Receiver 與動作
  • Receiver:真正執行業務邏輯的物件
  • Invoker:持有命令,觸發執行
  • Client:建立具體命令並設定給 Invoker

優缺點

優點缺點
易構建命令佇列可能產生大量具體命令類別
支援日誌、撤銷/重做增加系統複雜度
新命令易擴充(OCP)
接收者可決定是否執行

Java 實作範例:MP3 播放器


// 1. Command 介面
public interface Command {
    void execute();
    void undo();
}

// 2. Receiver
public class MP3Player {
    public void play()  { System.out.println("播放音樂"); }
    public void stop()  { System.out.println("停止播放"); }
    public void next()  { System.out.println("下一首"); }
    public void prev()  { System.out.println("上一首"); }
}

// 3. Concrete Commands
public class PlayCommand implements Command {
    private MP3Player player;
    public PlayCommand(MP3Player p) { this.player = p; }
    public void execute() { player.play(); }
    public void undo() { player.stop(); }
}

public class NextCommand implements Command {
    private MP3Player player;
    public NextCommand(MP3Player p) { this.player = p; }
    public void execute() { player.next(); }
    public void undo() { player.prev(); }
}

// 4. Invoker
public class RemoteControl {
    private Command[] onCommands;
    private Command[] offCommands;
    private Command lastCommand;

    public RemoteControl(int slots) {
        onCommands = new Command[slots];
        offCommands = new Command[slots];
    }

    public void setCommand(int slot, Command on, Command off) {
        onCommands[slot] = on;
        offCommands[slot] = off;
    }

    public void onButtonPressed(int slot) {
        onCommands[slot].execute();
        lastCommand = onCommands[slot];
    }

    public void offButtonPressed(int slot) {
        offCommands[slot].execute();
        lastCommand = offCommands[slot];
    }

    public void undoButtonPressed() {
        if (lastCommand != null) lastCommand.undo();
    }
}

// 5. Client 組裝
public class Main {
    public static void main(String[] args) {
        MP3Player player = new MP3Player();
        RemoteControl remote = new RemoteControl(2);

        remote.setCommand(0, new PlayCommand(player), new StopCommand(player));
        remote.setCommand(1, new NextCommand(player), new PrevCommand(player));

        remote.onButtonPressed(0);  // 播放
        remote.onButtonPressed(1);  // 下一首
        remote.undoButtonPressed(); // 撤銷:上一首
    }
}

應用場景

  • GUI 按鈕、選單項目動作封裝
  • 多層級 Undo/Redo(文字編輯器、繪圖工具)
  • 工作佇列、排程器、交易日誌
  • 巨集指令、腳本引擎

設計心得

命令模式的核心是「抓住主要矛盾」——將易變的「動作」抽離封裝,讓系統在擴充新功能時不修改既有結構,完美體現開放封閉原則。GoF 四人幫以此模式展示了物件導向設計「封裝變化」的經典智慧。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved