命令模式,顾名思义,将请求封装成命令对象,请求者的请求以命令的形式传达给执行者。
为什么要这么做呢,先从一个例子开始讲吧。
我们要设计一个遥控器,可以控制家中电器的开关,按照代码的逻辑怎么写?譬如把家中电器打开
if(appliance==ligjht){
ligjht.on;
}else if(appliance==waterheater){
waterheater.on;
}else{
}
这样,每加一种电器,我们就加一个判断,电器多了去了,是不是要写飞机,而且,最重要的是我们每次都要去修改这部分代码,这可不是什么好办法。
于是命令模式就可以像幽灵一样晃出来了在,怎么做呢?
和尚接口写得好,天下武功出少林。传承扩展从抽象接口开始。我们先定义一个命令接口。
public interface commond{
public void execute();
}
接下来就是开灯,实现命令接口,把他封装成一个开灯命令,lightOnCommond,开热水器封装成封装成 waterheaterOnCommond
public class LightOnCommond() implements commond{
Light light;
public LightOnCommond(Light light){
this.light=light;
}
public void execute(){
light.on;
}
我们按下对应的开关,就执行相应的命令,新的电器对应新的开关,这样的思路是不是清晰明了简单的多了。
以上例子,大概明白命令模式是干什么的了,但是,命令模式是怎么工作,整个流程是怎样的呢,让我们从餐馆的实例中找到答案。
顾客写订单,订单给服务员,服务员通知厨师,厨师按要单子做饭,这个过程我们细化一下
等量代换
通过餐馆的工作模式,我们成功看到client,commmond,invoker,receiver这些命模式中的角色。
意义是什么呢?
解耦与控制
实现了client和receiver之间的解耦,client发出请求,并不需要关心receiver是谁,等结果就好。receiver呢,也不用清楚请求从哪来,只需要按照命令操作。
现在我们把invoker和receivevr之间的commond单独拿出来了,当请求发出,这个commond可以给他排队,可以记录日志,可以记录各种各样的状态,可以撤销,在发出到实现的的时间里可以为所欲为。
我们的工程
命令字这个词很熟悉,新的wf框架接口的请求到实现是通过命令字进行的。这里的就有命令模式的思想。
整个请求简化如下
根据命令字获取一个实现类(这相当于得到一个具体的命令类)
AbsBusFacadeSupport abfs = BllFactory.getBllService(httpReq.getCmd());
//接下来这一步调用了命令类的实现方法execute。AbsBusFacadeSupport 这就等于commond接口
BusinessRes businessRes = abfs.doBusiness(hbody);
//doBusiness做了什么呢,调用了perform();
FacadeRes> out = perform(in);
perform()是我们在各个命令字对应的实现类下的具体方法,也就是receiver。
Hystrix
话题回来了,hystrix肯定是用了命令模式的,而且整个框架基于命令模式而生。
为什么呢。探究本源,Hystrix是什么,一个防御机制框架,也可以说是预防。预防什么呢?预防当上游服务挂了或者下游服务请求量过高时引发问题导致请求方整个服务不可用产生的雪崩效应。它怎么做的呢?简单地说他用了一个线程池,
请求先放到对应业务分配的线程池里,线程池里的请求超时,异常过多,或流量过大线程池中请求满了拒绝请求。。。时返回FallBack的预先准备的结果。
你看,它控制的对象是谁?是请求。请求怎么控制?封装成了命令对象。然后命令模式说这种事舍我其谁。
Hystrix有两个请求命令 HystrixCommand、HystrixObservableCommand。
- HystrixCommand 执行的本体方法是run(),run里你要让receiver的实现。
HystrixCommand用在依赖服务返回单个操作结果的时候。有两种执行方式
execute():同步执行。从依赖的服务返回一个单一的结果对象,或是在发生错误的时候抛出异常。该方法是通过queue()返回的异步对象Future
的get()方法来实现同步执行的。 queue();异步执行。直接返回一个Future对象,其中包含了服务执行结束时要返回的单一结果对象。通过toObservable()获得一个Cold Observable。
- HystrixObservableCommand 执行的本体方法是construct()
HystrixObservableCommand 用在依赖服务返回多个操作结果的时候。它也实现了两种执行方式
observe():返回Obervable对象,他代表了操作的多个结果,他是一个HotObservable
toObservable():同样返回Observable对象,也代表了操作多个结果,但它返回的是一个Cold Observable
到这我们已经把Rxjava和观察者模式勾出来了,请求的处理基于此实现。
Rx就是ReactiveX,官方定义是:
Rx是一个函数库,让开发者可以利用可观察序列和LING风格查询操作符来编写异步和基于时间的程序。
RxJava是什么
一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库
Cold Observables在被订阅后运行,也就是说,observables序列仅在subscribe函数被调用后才会推送数据。与Hot Observables不同之处在于,Hot Observables在被订阅之前就已经开始产生数据。