说明
前面有一篇文章提到过一个设计模式,是工厂模式和策略模式的使用。在项目中非常的普遍。这次我要介绍的是责任链模式,这个模式也非常的常见。
逻辑介绍
假设我们需要做到一个订单下单,一般来说订单下单需要做到一层一层的检测。如果其中有一层检测错误,那就直接抛出下单失败。并且丢出错误信息即可。如果是一般的写法。那就是一个长代码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()方法而已。
有时候写代码的时候就会有这种感觉,原来我现在写的东西就是之前的某某东西。或者某某框架中的实现方法其实和我这个一模一样,只是换了个皮而已,内核是一样的。也就是所谓触类旁通的感觉。