微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

第十七章·命令模式

一、命令模式概述

命令模式可以将请求发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。

定义:
命令模式:将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作。

二、命令模式的结构和实现

2.1 命令模式的结构

命令模式包含以下4个角色:

  1. Command(抽象命令类):抽象命令类一般是一个抽象类或接口,在其中声明了用于执行请求的execute()等方法,通过这些方法可以调用请求接收者的相关操作。
  2. ConcreteCommand(具体命令类):具体命令类是抽象命令类的子类,实现了在抽象命令类中声明的方法,它对应具体的接收者对象,将接收者对象的动作绑定其中。具体命令类在实现execute()方法时,将调用接收者对象的相关操作(Action)。
  3. Invoker(调用者)调用者即请求发送者,它通过命令对象来执行请求。
  4. Receiver(接收者):接收者执行与请求相关的操作,具体实现对请求的业务处理。

2.2 命令模式的实现

//请求调用

/**
 * 菜单项,充当请求调用者
 */
public class MenuItem {

    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void click(){
        System.out.println("单击功能键:");
        command.execute();
    }

}


/**
 * 主菜单
 */
public class Menu {

    private ArrayList<MenuItem> menuItems = new ArrayList<>();

    public void addMenuItem(MenuItem menuItem){
        menuItems.add(menuItem);
    }

}

//抽象命令类

/**
 * 抽象命令类
 */
public abstract class Command {

    public abstract void execute();

}

//具体命令类

/**
 * 创建命令类,具体命令类
 */
public class CreateCommand extends Command{

    private BoardScreen boardScreen;

    public CreateCommand(BoardScreen boardScreen){
        this.boardScreen = boardScreen;
    }

    @Override
    public void execute() {
        boardScreen.create();
    }
}

/**
 * 编辑命令类,具体命令类
 */
public class EditCommand extends Command{

    private BoardScreen boardScreen;

    public EditCommand(BoardScreen boardScreen){
        this.boardScreen = boardScreen;
    }

    @Override
    public void execute() {
        boardScreen.edit();
    }
}

/**
 * 打开命令类,具体命令类
 */
public class OpenCommand extends Command{

    private BoardScreen boardScreen;

    public OpenCommand(BoardScreen boardScreen){
        this.boardScreen = boardScreen;
    }

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

//请求接收者

/**
 * 公告板系统界面类
 */
public class BoardScreen {

    public void open(){
        System.out.println("公告板界面打开功能");
    }

    public void create(){
        System.out.println("公告板界面创建功能");
    }

    public void edit(){
        System.out.println("公告板界面编辑功能");
    }
}

//客户端

public class Client {

    public static void main(String[] args) {


        /**
         * 案例需求描述:
         * 开发一个公告板系统,系统提供一个菜单Menu,在主菜单中包含了一些菜单项MenuItem,
         * 可以通过Menu类的addMenuItem()方法增加菜单项。
         * 菜单项的主要方法是click(),每一个菜单项包含一个抽象命令类,具体命令类包括openCommand(打开命令),
         * createCommand(新建命令),editCommand(编辑命令)等,命令类有一个execute()方法,
         * 用于调用公告板系统界面类(BoardScreen)的open(),create(),edit()等方法。
         * 请使用命令模式设计该系统。
         */

        BoardScreen boardScreen = new BoardScreen();
        Command create, edit, open;
        create = new CreateCommand(boardScreen);
        edit = new EditCommand(boardScreen);
        open = new OpenCommand(boardScreen);

        MenuItem menuItem = new MenuItem();
        menuItem.setCommand(create);
        menuItem.click();

        menuItem.setCommand(edit);
        menuItem.click();

        menuItem.setCommand(open);
        menuItem.click();

        Menu menu = new Menu();
        menu.addMenuItem(menuItem);

    }

}

三、命令模式的优缺点和适用环境

3.1 命令模式的优点

  1. 降低了系统的耦合度
  2. 增加新的命令很容易
  3. 可以比较容易地设计一个命令队列或宏命令
  4. 为请求的撤销和恢复操作提供了一种设计和实现方案

3.2 命令模式的缺点

  1. 使用命令模式可能会导致某些系统有过多的具体命令类

3.3 命令模式的适用环境

  1. 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互
  2. 系统需要在不同的时间指定请求,将请求排队和执行请求
  3. 系统需要支持命令的撤销操作和恢复操作
  4. 系统需要将一组操作组合在一起形成宏命令(组合命令)

【参考文献】:
本文是根据刘伟的《Java设计模式》一书的学习笔记,仅供学习用途,勿做其他用途,请尊重知识产权。

【本文代码仓库】:https://gitee.com/xiongbomy/java-design-pattern.git

原文地址:https://www.jb51.cc/wenti/3280206.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐