【設計模式】Java設計模式 – 命令模式

Java設計模式 – 命令模式

😄生命不息,寫作不止
🔥 繼續踏上學習之路,學之分享筆記
👊 總有一天我也能像各位大佬一樣
🏆 一個有夢有戲的人 @怒放吧德德
🌝分享學習心得,歡迎指正,大家一起學習成長!

image

簡介

命令模式(Command Pattern)是一種數據驅動的設計模式,它屬於行為型模式。請求以命令的形式包裹在對象中,並傳給調用對象。調用對象尋找可以處理該命令的合適的對象,並把該命令傳給相應的對象,該對象執行命令。
                                                                                                                                                    ———— 菜鳥聯盟

命令模式解析

命令模式會將一個請求封裝為一個介面對象,由各種功能去實現其方法,在詳細命令類中,通過聚合的方式將具體方法進行抽取調用。
UML圖:
image

命令模式角色和職責

1)、Invoker:調用者角色
2)、Command:命令角色,需要執行的所有命令,(抽象類或介面)
3)、Receiver:命令接受者,知道如何實施執行某個命令
4)、ConcreteCommand:將一個接受對象和一個命令相互綁定,調用具體應操作的方法。

命令模式實例

通過智慧家居的例子來學習命令模式,有一個遙控器,上面集成了好多台設備的開關操作,有燈光、電視等控制按鈕。採用命令模式來管理控制,具體以下一步一步解析。首先看看具體的類圖:
image

本次的類結構看起來比較複雜,其實原理都是Java面向對象。

本次實驗通過定義命令介面,裡面包含執行的命令,在通過各種各樣設備去實現命令介面及其方法,不同設備的不同操作,如開、關,各種視為一個類,在這個類中實現不同的操作方法,雖然命令不同,但是可以通過聚合的方式,使用命令接受者類中去實現具體的不同方法進行分別調用。最後定義遙控器定義命令組並且為按鈕去綁定相應的實現命令。

程式碼如下,會一步一步解釋。

①、定義命令角色

命令角色可以是介面也可以是抽象類,根據本次的案例設計為介面。

只有一個執行方法。

package com.lyd.demo.command;

/**
 * @Author: lyd
 * @Description: 介面 - 命令
 * @Date: 2022-09-03
 */
public interface Command {
    public void execute(); // 執行方法
}

②、定義空命令

定義空命令是為了防止判空

package com.lyd.demo.command;
/**
 * @Author: lyd
 * @Description: 空命令方法,簡化空判斷
 * @Date: 2022-09-03
 */
public class NoCommand implements Command {
    @Override
    public void execute() {
    }
}

③、定義接受者

接收者就是具體的實現方法。

package com.lyd.demo.command.light;
/**
 * @Author: lyd
 * @Description: 被聚合類,也就是真正細節執行方法
 * @Date: 2022-09-03
 */
public class LightReceive {
    public void on() {
        System.out.println(" 燈光已打開... ");
    }
    public void off() {
        System.out.println(" 燈光已關閉... ");
    }
}

④、定義實現類

燈光打開類,通過聚合方式獲取具體實現方法;燈光實現類實現命令介面,實現執行方法(調用聚合類中的打開方法)

package com.lyd.demo.command.light;
import com.lyd.demo.command.Command;
/**
 * @Author: lyd
 * @Description: 實現類 - 點燈打開類
 * @Date: 2022-09-03
 */
public class LightOnCommand implements Command {
    // 聚合
    LightReceive lightReceive;
    public LightOnCommand(LightReceive lightReceive) {
        this.lightReceive = lightReceive;
    }
    @Override
    public void execute() { // 燈光打開命令只需要調用燈光開啟的方法
        lightReceive.on();
    }
}

關閉命令也是如此設置,這裡不粘貼程式碼了

⑤、定義遙控器

因為遙控器有許多設備的開關,定義相應開關按鈕的命令組,通過構造方法去初始化,並把美格爾對象實例化為空命令對象。通過setCommand方法來綁定按鈕和命令,onButton是模擬按下開關時候調用的方法。

package com.lyd.demo.controller;
import com.lyd.demo.command.Command;
import com.lyd.demo.command.NoCommand;
/**
 * @Author: lyd
 * @Description: 遙控器
 * @Date: 2022-09-03
 */
public class RemoteController {
    // 開按鈕的命令組
    Command[] onCommand;
    // 關閉命令組
    Command[] offCommand;
    public RemoteController() { // 假設有舞台設備,每台設備都是開關命令
        onCommand = new Command[5];
        offCommand = new Command[5];

        // 初始化
        for (int i=0; i<5; i++) {
            onCommand[i] = new NoCommand();
            offCommand[i] = new NoCommand();
        }
    }
    /**
     * 給按鈕設置命令
     * @param no 編號-代表設備
     * @param onCommand - 開命令
     * @param offCommand - 關命令
     */
    public void setCommand(int no, Command onCommand, Command offCommand) {
        this.onCommand[no] = onCommand;
        this.offCommand[no] = offCommand;
    }
    /**
     * 按下開按鈕
     * @param no 根據編號去調用哪個設備的執行方法
     */
    public void onButton(int no) {
        onCommand[no].execute();
    }
    /**
     * 按下關按鈕
     * @param no 根據編號去調用哪個設備的執行方法
     */
    public void offButton(int no) {
        offCommand[no].execute();
    }
}

⑥、測試

以上介紹只是寫了一種設備,還可以直接添加其他設備,並不需要改動其他類。
結構圖:
image

程式碼如下:

package com.lyd.demo.test;

import com.lyd.demo.command.light.LightOffCommand;
import com.lyd.demo.command.light.LightOnCommand;
import com.lyd.demo.command.light.LightReceive;
import com.lyd.demo.command.tv.TvOffCommand;
import com.lyd.demo.command.tv.TvOnCommand;
import com.lyd.demo.command.tv.TvReceive;
import com.lyd.demo.controller.RemoteController;

/**
 * @Author: lyd
 * @Description: 測試類
 * @Date: 2022-09-03
 */
public class CommandTest {
    public static void main(String[] args) {
        // 創建燈光的接受者 - 具體方法類
        LightReceive lightReceive = new LightReceive();
        // 創建燈光的命令
        LightOnCommand lightOnCommand = new LightOnCommand(lightReceive);
        LightOffCommand lightOffCommand = new LightOffCommand(lightReceive);
        // 創建遙控器
        RemoteController remoteController = new RemoteController();
        // 綁定命令到相應的按鈕中
        remoteController.setCommand(0, lightOnCommand, lightOffCommand); // 綁定
        // 測試
        System.out.println("按下開燈按鈕》》》》》");
        remoteController.onButton(0); // 0 代表是燈光按鈕
        System.out.println("按下關燈按鈕》》》》》");
        remoteController.offButton(0);

        TvReceive tvReceive = new TvReceive();
        TvOnCommand tvOnCommand = new TvOnCommand(tvReceive);
        TvOffCommand tvOffCommand = new TvOffCommand(tvReceive);
        remoteController.setCommand(1, tvOnCommand, tvOffCommand);
        System.out.println("按下開啟電視按鈕》》》》》");
        remoteController.onButton(1);
        System.out.println("按下關閉電視按鈕》》》》》");
        remoteController.offButton(1);
    }
}

運行結果:
image

👍創作不易,可能有些語言不是很通暢,如有錯誤請指正,感謝觀看!記得一鍵三連哦!👍

今天的內容看起來並不簡單,但實質上除了設計模式的思路,其實就是Java的面向對象知識,只要肯動手多敲,就容易理解。