设计模式之命令模式(十二)
2019-05-01 本文已影响10人
3d0829501918
命令模式从名字上来理解就是老大发命令,小兵执行就是了,确实是这个意思。
已经参加工作的小伙伴是不是常常遇到这种事情,项目经理加需求,需求变动,项目工期。程序员除了每天敲代码还要和项目经理的沟通。项目经理和程序员的关系可以看成是命令模式。
什么是命令模式?
将一个请求封装为一个对象,从而使你可用不同的请求客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
命令模式有哪几种角色?
Command:定义命令统一接口(项目经理法宝一、功能流程图)
ConcreteCommand:接口实现者,用来执行具体的命令。(项目经理法宝二、具体需求文档)
Receiver:命令的实际执行者(程序员)
Invoker:命令的请求者,是命令模式中最重要的角色,这个角色用对各个命令进行控制(项目经理)
类图
经典代码
- Command 声明执行操作的接口
public abstract class Command {
// 具体执行者
protected Receiver receiver;
public Command(Receiver receiver) {
this.receiver = receiver;
}
public abstract void execute();
}
- 将一个接收者对象绑定一个动作,调用接收者相应操作实现execute方法
public class ConcreteCommand extends Command {
public ConcreteCommand(Receiver receiver) {
super(receiver);
}
@Override
public void execute() {
// 调用具体执行
receiver.action();
}
}
- Receiver类,知道如何实施与执行请求相关操作,任何类都可能作为一个接收者。
public class Receiver {
public void action () {
System.out.println("执行请求!");
}
}
- Invoker类要求该命令执行这个请求
public class Invoker {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void executeCommand() {
command.execute();
}
}
- 测试方法
public static void main(String[] args) {
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.executeCommand();
}
- 测试结果
执行请求!
命令模式的优缺点!
- 优点
它能较容易地设计一个命令队列。
在需要的情况下,可以较容易地将命令记入日志。
允许接收请求去的一方决定是否要否决请求。
可以容易地实现对请求的撤销和重做
由于加进新的具体命令类不影响其他的类,因此增加新的具体类命令类很容易。
- 缺点
类数量随命令数量增长而增长。可能造成类数量过多。
如果命令非常简单,实现起来就几行代码的事,而使用命令模式的话,不管
命令多简单,都需要写一个命令类来封装。
有趣的代码
- 声明执行操作的接口
public abstract class Command {
protected Demand demand;
public Command(Demand demand) {
this.demand = demand;
}
public abstract void excuteCommand();
}
- Java 程序员
public class JavaCommand extends Command {
public JavaCommand(Demand barbecuer) {
super(barbecuer);
}
@Override
public void excuteCommand() {
demand.addDemand();
}
}
- Android程序员
public class AndroidCommand extends Command {
public AndroidCommand(Demand barbecuer) {
super(barbecuer);
}
@Override
public void excuteCommand() {
demand.addDemand();
}
}
- 具体执行动作
public class Demand {
public void addDemand() {
System.out.println("新增一个需求");
}
public void modifyDemand () {
System.out.println("修改一个需求");
}
}
- 发布命令的项目经理
public class Manager {
private List<Command> orders = new LinkedList<Command>();
// 新增需求
public void setOrder(Command command) {
if (command.toString() .equals("com.company.JavaCommand@6d6f6e28") ) {
System.out.println("这个需求不予更改,哈哈哈");
System.out.println("拒绝需求"+command.toString()+"时间:"+new Date());
} else {
orders.add(command);
System.out.println("新增需求"+command.toString()+"时间:"+new Date());
}
}
// 取消需求
public void cancelOrder(Command command) {
orders.remove(command);
System.out.println("取消需求"+command.toString()+"时间:"+new Date());
}
// 通知全部执行
public void Notify() {
for (Command command : orders) {
command.excuteCommand();
}
}
}
- 测试方法
public static void main(String[] args) {
Demand boy = new Demand();
// 程序员
Command bake1 = new AndroidCommand(boy);
Command bake2 = new AndroidCommand(boy);
Command bake3 = new JavaCommand(boy);
// 项目经理
Manager girl = new Manager();
girl.setOrder(bake1);
girl.setOrder(bake2);
girl.setOrder(bake3);
girl.Notify();
}
}
- 执行结果
执行结果:
新增需求com.company.AndroidCommand@4554617c时间:Sun Mar 17 15:54:57 CST 2019
新增需求com.company.AndroidCommand@7f31245a时间:Sun Mar 17 15:54:57 CST 2019
这个需求不予更改,哈哈哈
拒绝需求com.company.JavaCommand@6d6f6e28时间:Sun Mar 17 15:54:57 CST 2019
新增一个需求
新增一个需求
命令模式的适用场景
对于大多数请求-响应模式的功能,比较适合使用命令模式,正如命令模式定义说的那样,命令模式对实现记录日志、撤销操作等功能比较方便。
小结
通过例子看出项目经理发布命令,程序员执行命令,项目经理和程序员是相辅相成,缺一不可,都很重要。看来设计模式无处不在呀。