古时候有一天,皇帝大发善心,要大赦天下而且还要减轻赋税,于是大臣们根据皇帝不同的旨意传达不同的指令,不管是什么指令,最终都是由老百姓来执行。这就是命令模式。
一、认识命令模式
1、概念
将客户的请求传入一个对象,请求不同传入的对象也不同。因此可实现二者之间的松耦合,以便适应变化。分离变化与不变的因素。
意思是什么呢?假如皇帝想要大赦天下,那么大臣们就可以根据皇帝的意思,传达大赦天下的指令。皇帝有想要减轻赋税,大臣们可以根据皇帝旨意,传达减轻赋税的指令,皇帝的请求不同,那么大臣们传达的指令也不同。现在应该明白了吧。
2、类图
![](https://img.haomeiwen.com/i4153190/986b1ec659d7776b.png)
从上面这张类图我们不难发现,皇帝的最终意思就是要让老百姓去执行,但是自己又不能亲力亲为,于是只把意思跟大臣们一说,大臣们颁布传达具体的指令,最终让老百姓去执行。
这里有五个角色,我们来分析一下:
(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,这就是命令模式,如有问题还请批评指正。
欢迎关注微信公众号:java的架构师技术栈,回复关键字可获取从小白到架构师的学习路线和视频书籍资源。感谢关注
微信公众号.png
网友评论