命令模式
定义
将一个请求封装成一个对象,从而让你使用不同的请求吧客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。
命令模式是一个高内聚的模式。
优缺点、应用场景
优点
- 类间解耦。调用者与接收者之间没有任何依赖关系。调用者只需要调用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 {@Overridepublic void find() {System.out.println("找到需求组。。。");}@Overridepublic void add() {System.out.println("客户要求增加一项需求");}@Overridepublic void delete() {System.out.println("客户要求删除一项需求");}@Overridepublic void change() {System.out.println("客户要求修改一项需求");}@Overridepublic void plan() {System.out.println("客户要求需求变更计划");}
}/*** 美工组*/
public class PageGroup extends Group {@Overridepublic void find() {System.out.println("找到美工组。。。");}@Overridepublic void add() {System.out.println("客户要求增加一个页面");}@Overridepublic void delete() {System.out.println("客户要求删除一个页面");}@Overridepublic void change() {System.out.println("客户要求修改一个页面");}@Overridepublic void plan() {System.out.println("客户要求页面变更计划");}
}/*** 代码组*/
public class CodeGroup extends Group {@Overridepublic void find() {System.out.println("找到代码组。。。");}@Overridepublic void add() {System.out.println("客户要求增加一项功能");}@Overridepublic void delete() {System.out.println("客户要求删除一项功能");}@Overridepublic void change() {System.out.println("客户要求修改一项功能");}@Overridepublic 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 {@Overridepublic void execute() {super.requirementGroup.find();super.requirementGroup.add();super.requirementGroup.plan();}
}/*** 需求组添加需求的命令*/
public class DeletePageCommand extends Command {@Overridepublic 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();}
}
结果
非命令模式
命令模式
参考书籍
秦小波《设计模式之禅》