👉文章示例代码👈

定义

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化。

四个角色

命令模式主要有以下四个角色:

  • 抽象命令类Command:声明执行操作的接口。
  • 具体命令类Concrete Command:是抽象命令类的具体实现类,持有接受者对象,同时通过调用接收者的功能来完成命令要执行的操作。
  • 接收者Receiver:执行命令功能的相关操作。
  • 调用者Invoker:拥有很多命令对象,并通过访问命令对象来执行相关请求,其不直接访问接收者。

场景示例

笔者女朋友在一家知识付费公司做人事兼老板助理,常常会接收到一些来自老板的工作安排。

笔者这里以此为例。假设这天下班,女朋友接到老板的以下几个工作安排:

  • 明早9点准时在公司公号上发布一篇xx的推文。
  • 上午和老板一起外出看讲座场地。
  • 安排明天下午两点的会议。

创建抽象命令类

/**
 * @author zhh
 * @description 抽象命令接口
 * @date 2020-03-02 16:31
 */
public interface Command {

    /**
     * 执行命令
     */
    void execute();
}

创建具体命令类

每一个具体的工作安排对应一个具体的命令类。

/**
 * @author zhh
 * @description 发送推文命令
 * @date 2020-03-02 16:33
 */
public class SendTweetsCommand implements Command {

    private Staff staff;

    public SendTweetsCommand(Staff staff) {
        this.staff = staff;
    }

    public void execute() {
        staff.sendTweets();
    }
}


/**
 * @author zhh
 * @description 看场地命令
 * @date 2020-03-02 16:37
 */
public class LookVenueCommand implements Command {

    private Staff staff;

    public LookVenueCommand(Staff staff) {
        this.staff = staff;
    }

    public void execute() {
        staff.lookVenue();
    }
}


/**
 * @author zhh
 * @description 安排会议命令
 * @date 2020-03-02 16:38
 */
public class AttendMeetingCommand implements Command {

    private Staff staff;

    public AttendMeetingCommand(Staff staff) {
        this.staff = staff;
    }

    public void execute() {
        staff.attendMeeting();
    }
}

创建接受者

/**
 * @author zhh
 * @description 接受者类
 * @date 2020-03-02 16:58
 */
public class Staff {

    private String name;

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

    /**
     * 发推文
     */
    public void sendTweets() {
        System.out.println(this.name + "早上9点准时在公司公号上发布一篇xx的推文");
    }

    /**
     * 看场地
     */
    public void lookVenue() {
        System.out.println(this.name + "上午和老板一起外出看讲座场地");
    }

    /**
     * 安排会议
     */
    public void attendMeeting() {
        System.out.println(this.name + "安排下午两点的会议");
    }
}

创建调用者

/**
 * @author zhh
 * @description 调用者类
 * @date 2020-03-02 16:43
 */
public class Boss {

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

    /**
     * 添加命令
     * @param command 命令
     */
    public void addCommand(Command command) {
        commandList.add(command);
    }

    /**
     * 发送命令
     */
    public void sendCommands() {
        for (Command command : commandList) {
            command.execute();
        }
        commandList.clear();
    }
}

测试类及输出

/**
 * @author zhh
 * @description 测试类
 * @date 2020-03-02 16:48
 */
public class Test {

    public static void main(String[] args) {
        Staff staff = new Staff("亚萍");
        Command sendTweetsCommand = new SendTweetsCommand(staff);
        Command lookVenueCommand = new LookVenueCommand(staff);
        Command attendMeetingCommand = new AttendMeetingCommand(staff);

        Boss boss = new Boss();
        boss.addCommand(sendTweetsCommand);
        boss.addCommand(lookVenueCommand);
        boss.addCommand(attendMeetingCommand);

        boss.sendCommands();
    }
}

测试类的输出结果如下:

亚萍早上9点准时在公司公号上发布一篇xx的推文

亚萍上午和老板一起外出看讲座场地

亚萍安排下午两点的会议

类结构图

以上示例类的结构图如下所示

image.png

总结

适用场景

  • 当请求调用者和请求接受者需要解耦时,命令模式使得调用者和接受者不直接交互。
  • 需要抽象出等待执行的行为。

优点

  • 降低系统的耦合度。
  • 良好的扩展性。新增或者删除命令不会影响其他类。

缺点

对于每一个具体的操作都需要对应设计一个具体的命令类,这会导致类的数目的增加,增加系统的复杂性。

参考