最近学习微服务的hystrix组件,了解到hystrix使用到了命令模式。我觉得设计模式的学习不能脱离实际,你必须知道什么情况下需要使用到它,该如何去使用,否则就没有学习到精髓,学习的目的还是要使用,将它应用到实际的工作中,让我们的代码更加的简洁易读、更易扩展。
首先我们来看一下官方是如何定义它的。
命令模式:Encapsulate a request as an object,there by letting you parameterize clients with different requests,queue or log requests,and support undoable operations. (将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。)官方的解释看起来有点难以理解,简单来说就是,将客户端请求封装成一个对象,从而把命令的请求和命令执行两个操作分开,实现请求方和执行方的松耦合。
命令模式包含以下主要角色:
抽象命令类(Command)角色:声明执行命令的接口,拥有执行命令的抽象方法 execute()。具体命令角色(Concrete Command)角色:是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。实现者/接收者(Receiver)角色:执行命令功能的相关操作,是具体命令对象业务的真正实现者。调用者/请求者(Invoker)角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。结构图如下: 我们需要根据实际的业务场景,找出相应的请求者和接收者,然后再进行代码的编写。找到这几个角色是很重要的!
这里借用小傅哥《重学java设计模式》一书中的例子来做讲解。有兴趣的同学也可以看一看这本书,对设计模式的讲解很透彻。
在这张图片中,模拟了客户点餐下单的过程。客户点餐与厨师的烹饪是两个过程,现在我们来找出这个业务场景中的几个命令模式的角色,命令、接收者、请求者。大家应该很快就能找出,命令(客户点菜)、接收者(厨师)、请求者(小二)。
1、首先创建命令接口
public interface Food { public void execute(); }客户点单的命令接口,接口需要包含执行命令的方法execute()。
2、实现具体命令接口,客户具体的点菜命令
public class GuangDongFood implements Food { private Cooker cooker; public GuangDongFood(Cooker cooker) { this.cooker = cooker; } @Override public void execute() { cooker.doCooking(); } }这里只实现其中一种,其它的命令实现类似。命令实现需要包含接收者对象Cooker。
3、请求者的实现,即小二
public class XiaoEr { List<Food> list = new ArrayList<>(); //点单 public void order(Food food) { list.add(food); } //下单 public void placeOrder() { list.forEach(Food::execute); } }请求者通过命令对象来执行做菜的请求,不直接访问接收者(厨师)。
4、接收者接口,即厨师接口
public interface Cooker { void doCooking(); }5、接收者实现,需要实现具体的业务(做菜)
public class GuangDongCooker implements Cooker { @Override public void doCooking() { System.out.println("广东厨师烹饪广东菜.........."); } }这里也只给出一种,其它的厨师实现也是类似。
6、测试类
public class CommandTest { public static void main(String[] args) { XiaoEr xiaoEr = new XiaoEr(); xiaoEr.order(new GuangDongFood(new GuangDongCooker())); xiaoEr.order(new HuNanFood(new HuNanCooker())); xiaoEr.order(new JangNanFood(new JiangNanCooker())); xiaoEr.placeOrder(); } }这样就实现了整个点餐的过程,客户点单与具体的厨师做菜是两个独立的过程。具体的代码在文章最后的链接处。
说句实话,我也没搞太明白,只知道HystrixCommand这里使用了命令模式来包装依赖调用逻辑。只有去看hystrix的源码才能搞明白了,目前我是还没有搞清楚,我会继续看的,搞明白了再来补充。如果您理解清楚了,也麻烦您给讲讲,谢谢!
源码地址 参考1:小傅哥《重学java设计模式》 参考2:命令模式(详解版)
关于命令模式,我就先说这么多了,主要还是命令模式的应用,一定要在实际的业务中去使用才能真正的掌握它,关于它的优缺点这里就不再说了,用了才能知道,不用说了也没用。我个人也还有些没有弄明白的地方,当我有了新的收获,我会继续更新这篇文章,也请大家给予指导和建议,谢谢!