美文网首页
Apache commons-chain 核心分析

Apache commons-chain 核心分析

作者: 洋洋洒洒_6a20 | 来源:发表于2018-11-19 15:05 被阅读0次

    类和接口关系分析

    class.jpg

    接口定义

    Command 命令接口

    public abstract interface Command
    {
      public static final boolean CONTINUE_PROCESSING = 0;
      public static final boolean PROCESSING_COMPLETE = 1;
    
      public abstract boolean execute(Context paramContext)
        throws Exception;
    }
    

    Context 上下文接口

    public abstract interface Context extends Map
    {
    }
    

    Chain 执行链接口

    public abstract interface Chain extends Command
    {
      public abstract void addCommand(Command paramCommand);
    
      public abstract boolean execute(Context paramContext)
        throws Exception;
    }
    

    Filter 拦截器接口(相当于一种特殊的命令)

    public abstract interface Filter extends Command
    {
      //后置处理
      public abstract boolean postprocess(Context paramContext, Exception paramException);
    }
    

    ContextBase 上下文实现类 拓展的是HashMap

    public class ContextBase extends HashMap
      implements Context
    {
    //这里可以根据自己的业务定制上下文
    }
    

    ChainBase 执行链实现类

    public class ChainBase
      implements Chain
    {
    
      //要执行的命令数组
      protected Command[] commands = new Command[0];
    
      protected boolean frozen = false;
    
      public ChainBase()
      {
      }
    
      public ChainBase(Command command)
      {
        addCommand(command);
      }
    
      public ChainBase(Command[] commands)
      {
        if (commands == null) {
          throw new IllegalArgumentException();
        }
        for (int i = 0; i < commands.length; ++i)
          addCommand(commands[i]);
      }
    
      public ChainBase(Collection commands)
      {
        if (commands == null) {
          throw new IllegalArgumentException();
        }
        Iterator elements = commands.iterator();
        while (elements.hasNext())
          addCommand((Command)elements.next());
      }
    
      public void addCommand(Command command)
      {
        if (command == null) {
          throw new IllegalArgumentException();
        }
        if (this.frozen) {
          throw new IllegalStateException();
        }
        Command[] results = new Command[this.commands.length + 1];
        System.arraycopy(this.commands, 0, results, 0, this.commands.length);
        results[this.commands.length] = command;
        this.commands = results;
      }
    
      //执行命令
      public boolean execute(Context context)
        throws Exception
      {
        if (context == null) {
          throw new IllegalArgumentException();
        }
    
        this.frozen = true;
    
        //执行结果
        boolean saveResult = false;
        Exception saveException = null;
        int i = 0;
        int n = this.commands.length;
        label79:
        for (i = 0; i < n; ++i) {
          try {
            //返回执行结果如果为true就代表不往下执行
            saveResult = this.commands[i].execute(context);
            if (saveResult)
              break label79;
          }
          catch (Exception e) {
            //异常处理
            saveException = e;
            break label79;
          }
    
        }
    
        if (i >= n) {
          label79: --i;
        }
        //过滤器处理状态
        boolean handled = false;
        //过滤器处理结果
        boolean result = false;
        //从停止的位置反向执行过滤器
        for (int j = i; j >= 0; --j) {
          if (!(this.commands[j] instanceof Filter)) continue;
          try {
            //执行过滤器的postprocess方法,并传入异常
            result = ((Filter)this.commands[j]).postprocess(context, saveException);
    
            if (result) {
              handled = true;
            }
          }
          catch (Exception e)
          {
          }
    
        }
    
        //判断过滤器的处理状态 如果过滤器处理不了就抛给上层处理
        if ((saveException != null) && (!(handled))) {
          throw saveException;
        }
        return saveResult;
      }
    
      Command[] getCommands()
      {
        return this.commands;
      }
    }
    

    举个栗子

    //声明要执行的命令

    class FirstStep implements Command{
        public boolean execute(Context paramContext){
            System.out.println("执行第一步");
            return false;
        }
    } 
    
    class SecondStep implements Command{
        public boolean execute(Context paramContext){
            System.out.println("执行第二步");
            return false;
        }
    } 
    
    class ThirdStep implements Command{
        public boolean execute(Context paramContext){
            System.out.println("执行第三步");
            return false;
        }
    } 
    

    //声明拦截器 可选

    class SetBeforeFilter implements Filter {
        public boolean execute(Context paramContext){
            System.out.println("执行前");
            return false;//return false为继续往下执行
        }
        
        //后置执行方法,所有command执行完后会反过来执行postprocess
        public boolean postprocess(Context paramContext, Exception paramException){
            //这里可以处理异常,如果paramExeception 部位空的话
            System.out.println("异常信息"+paramException);
            System.out.println("后置执行");
            return true; //返回是否处理,如果异常信息不为空并且返回false程序会抛出异常
        }
    }
    

    //构建执行链

    注意:链是按顺序执行的

    class StepChain extends ChainBase{
        //这里通过构造器初始化执行链
        public StepChain(){
            addCommand(new SetBeforeFilter());
            addCommand(new FirstStep());
            addCommand(new SecondStep());
            addCommand(new ThirdStep());
        }
    }
    

    //测试

    class Test{
        
        public static void main(String[] args) throws Exception {
            //上下文,用于多个command之间的数据传递
            Context context = new ContextBase();
            ChainBase chain = new StepChain();
            chain.execute(context);
        }
    
    }
    

    输出

    • 执行前
    • 执行第一步
    • 执行第二步
    • 执行第三步
    • 异常信息null
    • 后置执行

    适用范围

    适合复杂的业务流程并且业务流程后续会增加或变化的情况

    设计模式分析

    commons-chain 主要使用了责任链模式
    Command 类在实际使用的时候也可以通过模板模式拓展

    责任链模式的优点

    责任链模式屏蔽了处理过程,链中的每个类只需要处理好自己的事情,处理完后最终会返回一个处理结果(当然也可以不做
    任何处理),作为调用者可以不用知道到底是需要谁来处理的,这是责任链模式的核心,同时责任链模式也可以作为一种补救模式来使用。举个常用的例子,如常用的Struts2的拦截器,你可以通过简单的配置文件就可以将拦截器插入请求处理链中处理一些业务逻辑

    有人可能会问这种方式和分成多个方法然后在一个方法中调用有什么区别吗?

    首先区别还是有的,Java是一门面向对象的编程语言,都是在大多数情况下我们的业务处理都是一个service一竿子捅到底,这个明显就是用面向对象的语言做着面向过程的事,一个service类处理所有的业务逻辑那么这个类肯定非常大,代码也非常长,维护起来也不好维护,一个有几百行的业务方法维护起来通常要小心翼翼,因为一不小心改多了或删错某行代码那锅肯定甩不掉了,有些没有经验程序员写的方法可能都是public这种情况下一个类就会暴露过多的方法造成各个类之间的引用混乱,如果你想要删除一个public修饰的方法你需要考虑是否有其他类引用这个方法,这些坑前面的先驱都已经踩过了,所以才有了设计模式

    推荐下个人blog+bbs www.youngboy.vip

    相关文章

      网友评论

          本文标题:Apache commons-chain 核心分析

          本文链接:https://www.haomeiwen.com/subject/cqqafqtx.html