前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >透过源码学习设计模式4—HystrixCommand和命令模式

透过源码学习设计模式4—HystrixCommand和命令模式

作者头像
java达人
发布2019-07-31 16:05:52
2K0
发布2019-07-31 16:05:52
举报
文章被收录于专栏:java达人
简介:

在面对对象编程中,命令模式是一种行为模式,其中对象用于封装执行动作或稍后触发事件所需的所有信息。这些信息包括方法名称,拥有该方法的对象以及方法参数的值。命令模式也支持可撤销操作。

命令模式包括4个角色:

Command:定义命令的统一接口

ConcreteCommand:Command接口的实现者,用来执行具体的命令,某些情况下可以直接用来充当Receiver。

Receiver:命令的实际执行者

Invoker:命令的请求者,是命令模式中最重要的角色。这个角色用来对各个命令进行控制。

命令模式有如下优点:

1.降低对象之间的耦合度(将发出请求的对象和执行请求的对象解耦,即将调用者和执行者进行解耦)

2.新的命令可以很容易地加入到系统中。

3.可以比较容易地设计一个组合命令。

4.调用同一方法实现不同的功能

缺点:

可能会导致某些系统有过多的具体命令类。

Hystrix

Hystrix命令模式封装了命令运行逻辑(run)和服务调用失败时回退逻辑(getFallback)。其command抽象类是hystrixcommand,用于包装执行具有潜在风险功能的代码(通常指通过网络进行的服务调用),具备容错和延时,统计和性能指标捕获,断路器和舱壁功能。

该命令本质上是一个阻塞命令,但如果与observe()一起使用,则提供一个可观察的facade。

此模式的详情如下:

  1. 构造Hystrix命令对象,并调用run方法
  2. Hystrix将检查断路器开关是否打开,如果打开,则调用回退方法
  3. 如果断路器开关关闭,Hystrix将检查当前服务的线程池,看是否可以接受新请求。如果线程池已满,则调用回退方法
  4. 如果线程池可以接受新请求,那么Hystrix可以调用run方法来执行run逻辑
  5. 如果run执行失败,则调用回退方法并将健康状态返回到Hystrix指标
  6. 如果run执行超时,则调用回退方法并将健康状况返回到Hystrix指标
  7. 如果run成功执行,则返回正常结果
  8. 如果回退方法成功执行,它将返回回退执行结果
  9. 如果回退方法执行失败,则抛出异常

伪代码示例子

那是否使用命令模式,这两者有什么区别呢?我们通过一些伪代码来帮助理解.

有hystrixcommand之前:

代码语言:javascript
复制
public class SimpleHystrix {
  private RestService restService;
  private HttpClientService httpClientService;
  private OkHttpService  okHttpService;
    public void call(String callName) {
        if (callName.equals("httpclient")) {
httpClientService.do();
       } else if (callName.equals("okhttpclient")) {
okHttpService.do();
        } else if (callName.equals("restClient")) {
restService.do();
        }
    }
}
public class SimpleHystrixRun {
    public static void main(String[] args) {
        SimpleHystrix simpleHystrix = new SimpleHystrix();
        simpleHystrix.call("httpclient");
        simpleHystrix.call("okhttpclient");
        simpleHystrix.call("restClient");
    }
}

这里需要根据指令来调用对象的方法,如果需要新增command类型,那么就需要在SimpleHystrix里增加判断,这样SimpleHystrix始终要关注需要调用的外部服务,如果新增服务时需要改动代码,这样违背了面向接口编程的原则,同时代码也较难维护。

有HystrixCommand之后:

如图示,RibbonCommand继承HystrixCommand,它有三个子类

代码语言:javascript
复制
public class SimpleHystrix {
    private SimpleHystrixCommand simpleHystrixCommand;
    public void setSimpleHystrixCommand(SimpleHystrixCommand simpleHystrixCommand) {
        this.simpleHystrixCommand = simpleHystrixCommand;
    }
    public void call() {
        simpleHystrixCommand.execute();
    }
}
//SimpleHystrixRun为client
public class SimpleHystrixRun {
    public static void main(String[] args) {
// 这里service为命令的实际执行者,即Receiver
       RestService restService= newRestService();
//simpleHystrix为命令的请求者,即Invoker
        SimpleHystrix simpleHystrix = new SimpleHystrix();
//HttpClientRibbonCommand等是具体命令, ConcreteCommand
        simpleHystrix.setSimpleHystrixCommand(new HttpClientRibbonCommand(restService));
        simpleHystrix.call();
        HttpClientServicehttpClientService= newHttpClientService();
        simpleHystrix.setSimpleHystrixCommand(new OkHttpRibbonCommand(httpClientService));
        simpleHystrix.call();
        OkHttpService okHttpService= newOkHttpService();
        simpleHystrix.setSimpleHystrixCommand(new RestClientRibbonCommand(okHttpService));
        simpleHystrix.call();
    }
}

具体执行逻辑在Command中实现,如

ConcreteCommand:

代码语言:javascript
复制
public class HttpClientRibbonCommand implements SimpleHystrixCommand {
   @Override
   public void execute() {
    //do things
   }
}

将服务的实现封装到一个对象委托出去,由命令对象来实现具体的调用。只需要增加一个继承Command的类,然后在execute方法实现对应服务的调用以及其他操作即可,无需侵入业务代码。

java达人

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java达人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介:
  • Hystrix
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档