前面有一篇文章提到过一个设计模式,是工厂模式和策略模式的使用。在项目中非常的普遍。这次我要介绍的是责任链模式,这个模式也非常的常见。
假设我们需要做到一个订单下单,一般来说订单下单需要做到一层一层的检测。如果其中有一层检测错误,那就直接抛出下单失败。并且丢出错误信息即可。如果是一般的写法。那就是一个长代码if else 。如果校验规则越来越多。那么就可以使用责任链模式,把校验规则分开写,也会更加优雅。 话不多说。直接上代码
核心类,用于策略启动
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class ApplicationService { @Autowired private List<Filter> filters; //直接在外部注入ApplicationService并且执行mockedClient()即可启动责任链 public void mockedClient() { Task task = new Task(); // 这里task一般是通过数据库查询得到的 for (Filter filter : filters) { if (!filter.filter(task)) { return; } } // 过滤完成,后续是执行任务的逻辑 } }接口类,父级引用
public interface Filter { /** * 用于对各个任务节点进行过滤 */ boolean filter(Task task); }实现类1,用于风险拦截
import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; // 风控拦截 @Component @Order(90) public class RiskFilter implements Filter { @Override public boolean filter(Task task) { System.out.println("风控拦截"); return true; } }实现类2,用于时效性检测
// 时效性检验 @Component @Order(80) public class DurationFilter implements Filter { @Override public boolean filter(Task task) { System.out.println("时效性检验"); return true; } }实现类3,用于次数校验
import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; // 次数限制校验 @Component @Order(100) public class TimesFilter implements Filter { @Override public boolean filter(Task task) { System.out.println("次数限制检验"); return true; } }上下文类
/** * 用于策略运行的context上下文 */ public class Task { /** * 入参 */ private String params; /** * 中间参数 */ private String middle; /** * 结果 */ private String result; //下面是get set方法 }我这个代码中用到的框架是spring的依赖注入以及一个@order注解。可以帮助我们在直接注入整个List集合的Filter类的时候。可以控制一个顺序。
然后task类就是一个任务执行的上下文类,比如在订单下单的时候的一些入参。中间参数,特殊的结果值都可以获得。
这样的话可以轻松的做到一个接口实现的原则,易于拓展。每次有新的逻辑加入,只需要实现Filter并且调整位置注入责任链中即可,当有一些校验逻辑需要修改的时候,也只需要单独修改那个对应的校验类即可。对于系统的稳定性的帮助也很大,不会有改一大坨代码的时候那种牵一发动全身的感觉,对于新人来说代码理解也更加容易
其实这个责任链真的是非常非常的简单,如果看过我之前的文章。这个链接:简单好用的上下文写法 就会发现其实这2篇文章讲的是同一个东西,无非是把一个类中的多个小方法变成了一个类,task就是那篇文章中的context,一个个实现类中的filter()方法其实也就是上下文中的一个个first(),second(),third()方法而已。
有时候写代码的时候就会有这种感觉,原来我现在写的东西就是之前的某某东西。或者某某框架中的实现方法其实和我这个一模一样,只是换了个皮而已,内核是一样的。也就是所谓触类旁通的感觉。