附链
你也可以在这些平台阅读本文:
定义
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化。
四个角色
命令模式主要有以下四个角色:
- 抽象命令类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的推文
亚萍上午和老板一起外出看讲座场地
亚萍安排下午两点的会议
类结构图
以上示例类的结构图如下所示
总结
适用场景
- 当请求调用者和请求接受者需要解耦时,命令模式使得调用者和接受者不直接交互。
- 需要抽象出等待执行的行为。
优点
- 降低系统的耦合度。
- 良好的扩展性。新增或者删除命令不会影响其他类。
缺点
对于每一个具体的操作都需要对应设计一个具体的命令类,这会导致类的数目的增加,增加系统的复杂性。