一、认识命令模式
1、概念
将客户的请求传入一个对象,请求不同传入的对象也不同。因此可实现二者之间的松耦合,以便适应变化。分离变化与不变的因素。
意思是什么呢?假如皇帝想要大赦天下,那么大臣们就可以根据皇帝的意思,传达大赦天下的指令。皇帝有想要减轻赋税,大臣们可以根据皇帝旨意,传达减轻赋税的指令,皇帝的请求不同,那么大臣们传达的指令也不同。现在应该明白了吧。
2、类图
从上面这张类图我们不难发现,皇帝的最终意思就是要让老百姓去执行,但是自己又不能亲力亲为,于是只把意思跟大臣们一说,大臣们颁布传达具体的指令,最终让老百姓去执行。
这里有五个角色,我们来分析一下:
(1)抽象命令接口Command(圣旨):声明执行的方法。
(2)具体命令对象ConcreteCommand(具体圣旨):具体的命令。
(3)接受者对象Receiver(老百姓):接受者对象,真正执行命令的对象。
(4)传递命令对象Invoker(大臣):持有命令对象,要求Receiver执行请求。
(5)客户端对象Client(皇帝):创建具体命令,设置命令对象的接受者。
3、命令模式与代理模式的区别
这个模式乍一看有点像代理模式,怎么看都是大臣是一个代理,其实不是,在这里我们提前说明一下,免得你稀里糊涂看完了一头雾水,下面进行一个对比分析。
(1)在代理(委托)模式中,调用者就是委托者,执行者就是被委托者,委托者和被委托者接口定义是相同的。命令模式不同,调用者不关注执行者的接口定义是否和它一致。
我们还是拿皇帝与大臣的关系举例子,代理模式中,要求皇帝和大臣们接口定义一样,也就是执行一样的操作。但是命令模式不同,皇帝和大臣的接口定义可以不一致,皇帝可以有自己其他的想法。
(2)在调用时机上,代理模式的具体执行是只能在特定的调用者内部执行(接口相同);命令模式的具体执行可以在任何调用者内部执行(接口不相同也可以)。
意思是什么呢?在代理模式中大臣们只执行一个皇帝(同一个人,谁当皇帝都只听朱元璋的)的命令,命令模式不一样,大臣们可以执行好几个皇帝的命令,也就是说不管谁当皇帝,都只听在任皇帝的。
现在你能分清了吧,那我们就具体来看一下命令模式如何实现的。
二、代码实现命令模式
第一步:创建接受者(老百姓)
public class People { //执行赦免命令 public void exePardonCommand() { System.out.println("老百姓执行赦免命令"); } //执行减税命令 public void exeReduceTaxCommand() { System.out.println("老百姓执行减税命令"); } }
第二步:抽象命令接口Command(圣旨)
public interface Command { public void execute(); }
第三步:具体命令对象ConcreteCommand(具体圣旨)
首先是大赦天下
//大赦天下 public class PardonCommand implements Command{ People people; public PardonCommand(People people) { this.people = people; } //大臣们也不会执行,真正执行的是百姓 @Override public void execute() { people.exePardonCommand(); } }
然后是减轻赋税
public class ReduceTaxCommand implements Command{ People people; public ReduceTaxCommand(People people) { this.people = people; } //大臣们也不会执行,真正执行的是百姓 @Override public void execute() { people.exeReduceTaxCommand(); } }
第四步:传递命令对象Invoker(大臣)
public class Minister { //大臣们把皇帝的旨意都创建好了 private Command pardomCommand,reduceTaxCommand; public Minister(Command pardomCommand, Command reduceTaxCommand) { this.pardomCommand = pardomCommand; this.reduceTaxCommand = reduceTaxCommand; } //然后大臣让老百姓去真正执行就OK了 public void pardon() { pardomCommand.execute(); } public void reduceTax() { reduceTaxCommand.execute(); } }
第五步:客户端对象Client(皇帝)模拟整个过程
public class Emperor { public static void main(String[] args) { //老百姓 People people=new People(); //皇帝的指令:大赦天下和减轻赋税 Command pardonCommand=new PardonCommand(people); Command reduceTaxCommand=new ReduceTaxCommand(people); //把命令传达给大臣 Minister minister=new Minister(pardonCommand, reduceTaxCommand); //大臣们去让老百姓去执行 minister.pardon(); minister.reduceTax(); } } //output: //老百姓执行赦免命令 //老百姓执行减税命令
三、分析命令模式
1、使用场景
命令模式适用于“请求-响应”模式的功能,把用户的请求封装成具体的命令对象,用户请求什么,我们就调用什么命令,用户无需知道命令执行逻辑是什么。
2、优缺点
优点:将用户的请求和请求的实现实现解耦,用户有了新需求,只需要增加一个需求实现对象即可。
缺点:请求比较多的时候,会使得整个类变得庞大。
OK,这就是命令模式,如有问题还请批评指正。