命令模式
定义
将一个请求封装成一个对象,从而让你使用不同的请求吧客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。
命令模式是一个高内聚的模式。
优缺点、应用场景
优点
- 类间解耦。调用者与接收者之间没有任何依赖关系。调用者只需要调用execute()方法即可,不需要了解哪个接收者执行。
- 可拓展性。
- 命令模式结合其他模式会更优秀。例如与责任链模式结合,实现命令族解析任务;结合模板方法模式,可以减少Command子类膨胀问题。
缺点
- 类的膨胀问题。如果有N个命令,则子类的数量就为N个,这可能会导致类的膨胀,需要慎重使用。
代码模拟场景
项目组有三个小组需求组、美工组、编码组,客户的每个“命令”都有可能涉及到多个组的响应,使用命令模式一方面接收客户的“命令”,另一方面根据“命令”组合出小组之间的分工。
实验小结
- 你永远也不知道用户到底怎么定义他的需求,每次的修改都相当于命令
- 如果对于每个命令都需要new来处理,那么每次都需要创建一个场景类,而且是手动的执行命令中的每个细节
- 命令模式要求,将一个命令中所有的细节都交给Command的实现类来做,执行命令时由唯一执行人Invoker来执行,而客户的需求只跟Invoker说明,由Invoker发布命令
命令模式
UML图
部门抽象及部门实体
/**
* 抽象组
*/
public abstract class Group {
// 甲乙双方分开办公,如果要和某个组讨论,首先要找到这个组
public abstract void find();
// 被要求增加功能
public abstract void add();
// 被要求删除功能
public abstract void delete();
// 被要求修改功能
public abstract void change();
// 被要求给出所有的变更计划
public abstract void plan();
}
/**
* 需求组
*/
public class RequirementGroup extends Group {
@Override
public void find() {
System.out.println("找到需求组。。。");
}
@Override
public void add() {
System.out.println("客户要求增加一项需求");
}
@Override
public void delete() {
System.out.println("客户要求删除一项需求");
}
@Override
public void change() {
System.out.println("客户要求修改一项需求");
}
@Override
public void plan() {
System.out.println("客户要求需求变更计划");
}
}
/**
* 美工组
*/
public class PageGroup extends Group {
@Override
public void find() {
System.out.println("找到美工组。。。");
}
@Override
public void add() {
System.out.println("客户要求增加一个页面");
}
@Override
public void delete() {
System.out.println("客户要求删除一个页面");
}
@Override
public void change() {
System.out.println("客户要求修改一个页面");
}
@Override
public void plan() {
System.out.println("客户要求页面变更计划");
}
}
/**
* 代码组
*/
public class CodeGroup extends Group {
@Override
public void find() {
System.out.println("找到代码组。。。");
}
@Override
public void add() {
System.out.println("客户要求增加一项功能");
}
@Override
public void delete() {
System.out.println("客户要求删除一项功能");
}
@Override
public void change() {
System.out.println("客户要求修改一项功能");
}
@Override
public void plan() {
System.out.println("客户要求代码变更计划");
}
}
命令Command抽象与实现
/**
* 抽象命令类
*/
public abstract class Command {
// 定义好三个组,子类可以直接使用
protected RequirementGroup requirementGroup = new RequirementGroup();
protected PageGroup pageGroup = new PageGroup();
protected CodeGroup codeGroup = new CodeGroup();
// 只有一个方法:执行
public abstract void execute();
}
/**
* 需求组添加需求的命令
*/
public class AddRequirementCommand extends Command {
@Override
public void execute() {
super.requirementGroup.find();
super.requirementGroup.add();
super.requirementGroup.plan();
}
}
/**
* 需求组添加需求的命令
*/
public class DeletePageCommand extends Command {
@Override
public void execute() {
super.pageGroup.find();
super.pageGroup.delete();
super.pageGroup.plan();
}
}
执行人(实施)
/**
* 执行者
*/
public class Invoker {
private Command command;
// 客户发出命令
public Invoker setCommand(Command command) {
this.command = command;
// 这个地方自己加的,为了方便设置命令后执行
return this;
}
// 执行客户的命令
public void action(){
this.command.execute();
}
}
入口类
public class CommandMain {
public static void main(String[] args) {
// 硬核需求();
command();
}
// 命令模式
public static void command(){
Invoker<Command> invoker = new Invoker<>();
// 添加一个需求
Command addRequirementCommand = new AddRequirementCommand();
// 设置命令,在这里需要什么命令就直接new一个Command接口的实现类即可
Command deletePageCommand = new DeletePageCommand();
invoker.setCommand(addRequirementCommand); // 执行
invoker.setCommand(deletePageCommand);
invoker.rollback(addRequirementCommand.getClass()); // 客户要求回滚
invoker.action();
}
public static void 硬核需求(){
System.out.println("-----客户要求增加一项需求-----");
Group requirementGroup = new RequirementGroup();
// 找到需求组
requirementGroup.find();
// 添加需求
requirementGroup.add();
// 要求变更计划
requirementGroup.plan();
}
}
结果
非命令模式
命令模式
参考书籍
秦小波《设计模式之禅》