模式定义:
将请求封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。
目的:
解决命令的请求者和命令的实现者之间的耦合关系。也就是说命令发起者不需要执行相应的命令,而是交给别人去做。
优点:
对多个命令的统一控制。我们可以将命令发起者比作公司的老板,他不需要亲自去招聘人才,也不需要亲自去做财务报表,需要做的只是发出两个命令“HR去招聘人才;财务去做本年度财务报表”即可,这些命令有条不紊的被发送出来。
组成结构:
Command:定义命令的统一接口
ConcreteCommand:Command接口的实现者,用来执行具体的命令,某些情况下可以直接用来充当Receiver。
Receiver:命令的实际执行者
Invoker:命令的请求者,是命令模式中最重要的角色。这个角色用来对各个命令进行控制好比于公司老板。
代码示例
那么我们以一家公司平时的运转作为场景。
Invoker:
public class Boss {
Command[] commands = new Command[5];
public void setCommand(int index,Command command){
commands[index] = command;
}
//发送不同的指令
public void command(int index){
commands[index].execute();
}
}
Command:
public interface Command {
void execute();
}
ConcreteCommand:
财务类的命令
public class FinaceCommand implements Command{
Recevier recevier;
public FinaceCommand(Recevier recevier){
this.recevier = recevier;
}
@Override
public void execute() {
System.out.println("财务部门开始:");
recevier.on();
System.out.println("财务部门开始结束:");
recevier.off();
}
}
人力资源类的命令
public class HRCommand implements Command {
Recevier recevier;
public HRCommand(Recevier recevier) {
this.recevier = recevier;
}
@Override
public void execute() {
System.out.println("HR开始招聘");
recevier.on();
System.out.println("招聘结束");
recevier.off();
}
}
Receiver:真正的命令执行者
public interface Recevier {
void on();
void off();
}
public class Finance implements Recevier{
@Override
public void on() {
System.out.println("做本年度报表!");
}
@Override
public void off() {
System.out.println("报表出来啦,今年公司亏损!");
}
}
public class HR implements Recevier{
@Override
public void on(){
System.out.println("公司招人啦!");
}
@Override
public void off() {
System.out.println("人招满了打道回府。");
}
}
Test代码:
public class TestCommand {
public static void main(String[] args){
Boss boss = new Boss();
Recevier hr = new HR();
Recevier finance = new Finance();
Command HRCommand = new HRCommand(hr);
Command finaceCommand = new FinaceCommand(finance);
boss.setCommand(0, HRCommand);
boss.setCommand(1, finaceCommand);
boss.command(0);
boss.command(1);
}
}
/*
**OUTPUT**:
HR开始招聘
公司招人啦!
招聘结束
人招满了打道回府。
财务部门开始:
做本年度报表!
财务部门开始结束:
报表出来啦,今年公司亏损!
*/
从上述代码来看,命令模式反而使得代码臃肿,有人会说,为何不直接让Invoker有Recevier的实例,一个一个去执行Recevier的方法呢,虽然命令请求者和执行者耦合在一块了,但这样不是更加方便?
答案很简单。我们要牢记命令模式的初衷:对命令请求者(Invoker)和命令实现者(Receiver)的解耦,方便对命令进行各种控制。
如果两者不解耦会如何?打一个比方。公司老板同样的发出两个命令:招聘人才,做出财务报表,但是不同的是这个老板比较谨慎小心,财务人员做报表的时候他一定要盯着;HR进行面试是他也不放心,也要盯着。这就使得整个公司的运作都是串行,只有做出报表以后才能进行人才招聘。此时,将老板和执行人员解耦,老板只需要发出命令,让对应工作人员去执行即可,此时整个公司运转就变成了并行。