設計模式之命令模式

0x01.定義與類型

  • 定義:將「請求」封裝成對象,以便使用不一樣的請求。
  • 命令模式解決了應用程序中對象的職責以及它們之間的通訊方式
  • 類型:行爲型
  • UML類圖

command1.png

  • 代碼示例
/**
 * 命令接口類
 */
public interface Command {
    void executor();
}

/**
 * 命令1
 */
public class ConcreteCommand1 implements Command {

    private Receiver receiver;

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

    @Override
    public void executor() {
        receiver.action("concrete command 1.");
    }
}

/**
 * 命令2
 */
public class ConcreteCommand2 implements Command {

    private Receiver receiver;

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

    @Override
    public void executor() {
        receiver.action("concrete command 2.");
    }
}

/**
 * 命令執行人
 */
public class Invoker {

    private List<Command> commands = new ArrayList<>();

    public void addCommand(Command command) {
        commands.add(command);
    }

    public void executorCommands() {
        commands.forEach(Command::executor);
        commands.clear();
    }
}

/**
 * 命令接收者
 */
public class Receiver {

    public void action(String name) {
        System.out.println(name);
    }
}
  • 應用與測試
/**
 * 應用與測試
 */
public class Test {

    public static void main(String[] args) {
        //建立命令接收方
        Receiver receiver = new Receiver();

        //建立執行者
        Invoker invoker = new Invoker();

        //建立命令
        ConcreteCommand1 concreteCommand1 = new ConcreteCommand1(receiver);
        ConcreteCommand2 concreteCommand2 = new ConcreteCommand2(receiver);

        //添加命令
        invoker.addCommand(concreteCommand1);
        invoker.addCommand(concreteCommand2);

        //執行
        invoker.executorCommands();
    }
}
  • 輸出結果
concrete command 1.
concrete command 2.
  • 命令模式角色介紹html

    • 接收者(Receiver):真正執行命令的對象,負責執行與請求相關的操做
    • 命令接口(Command):定義命令的接口,封裝execute()、undo()等方法
    • 具體命令(ConcreteCommand):命令接口實現對象,實現命令接口中的方法,一般會持有接收者,並調用接收者的功能來完成命令要執行的操做
    • 請求者(Invoker):要求命令對象執行請求,一般會持有命令對象,包含Command接口變量

0x02.適用場景

  • 請求調用者和請求接收者須要解耦,使得調用者和接收者不直接交互
  • 須要抽象出等待執行的行爲

0x03.優缺點

1.優勢

  • 下降系統的耦合度
  • 容易擴展新命令或一組命令
  • 調用同一方法實現不一樣的功能

2.缺點

  • 命令的無限擴展會增長類的數量,提升系統實現複雜度

0x04.命令模式相關案例

  • 課程視頻的打開和關閉
/**
 * 命令接口
 */
public interface Command {
    void execute();
}

/**
 * 打開課程連接
 */
public class OpenCourseVideoCommand implements Command {

    private CourseVideo courseVideo;

    public OpenCourseVideoCommand(CourseVideo courseVideo) {
        this.courseVideo = courseVideo;
    }

    @Override
    public void execute() {
        courseVideo.open();
    }
}

/**
 * 關閉課程連接
 */
public class CloseCourseVideoCommand implements Command {

    private CourseVideo courseVideo;

    public CloseCourseVideoCommand(CourseVideo courseVideo) {
        this.courseVideo = courseVideo;
    }

    @Override
    public void execute() {
        courseVideo.close();
    }
}

/**
 * 命令接受類
 */
public class CourseVideo {

    private String name;

    public CourseVideo(String name) {
        this.name = name;
    }

    public void open () {
        System.out.println(this.name + "課程視頻開放。");
    }

    public void close () {
        System.out.println(this.name + "課程視頻關閉。");
    }
}

/**
 * 執行人
 */
public class Staff {

    private List<Command> commands = new ArrayList<>();

    public void addCommand (Command command) {
        commands.add(command);
    }

    public void executeCommands () {
        commands.forEach(Command::execute);
        commands.clear();
    }
}
  • 測試與應用
/**
 * 測試與應用
 */
public class Test {

    public static void main(String[] args) {
        //命令接收者
        CourseVideo courseVideo = new CourseVideo("Java設計模式精講");

        //建立命令
        OpenCourseVideoCommand openCourseVideoCommand = new OpenCourseVideoCommand(courseVideo);
        CloseCourseVideoCommand closeCourseVideoCommand = new CloseCourseVideoCommand(courseVideo);

        //建立執行人
        Staff staff = new Staff();

        //添加命令
        staff.addCommand(openCourseVideoCommand);
        staff.addCommand(closeCourseVideoCommand);

        //執行
        staff.executeCommands();
    }
}
  • UML類圖

command2.png

0x05.相關設計模式

  • 命令模式和備忘錄模式java

    • 適用備忘錄模式保存命令的歷史記錄

0x06.源碼中的命令模式

  • Runnable
  • junit.frame.work.Test

0x07.源碼地址

0x08.推薦閱讀

相關文章
相關標籤/搜索