上一节说到策略模式: https://blog.csdn.net/zhanglei082319/article/details/88980673
所谓的策略模式:就是将一些不定的业务需求抽象出来,作为一种特定的策略方式分开实现,当需要使用哪种策略时,就调用该策略的具体实现。
今天说一种新的设计模式:责任链模式
责任链模式在实际开发中应用非常广泛,绝大部分的框架源码,一般企业互联网项目的代码中都能看到责任链模式的影子。如activiti, dubbo , mybatis ,spring 等等,
责任链模式的抽象定义:将请求传给一个接收者链,由链将请求流转给目标对象。就是说责任链可以像一个链条一样一环套一环的将各个业务串联在一起,有顺序的执行下去。并且可以在执行中做一些自定义操作。
比如,我们在实际开发中会不会存在几个业务串行执行,或者就算不存在,我们是不是可以这样写着,后期如果需要在这个业务前面或者后面加上一层业务,我们也方便维护。
在这里就来个比较实际的责任链的案例使用:
1、新建一个责任链接口: Command是执行责任链方法的命令参数, 也是下一期需要讲的命令模式。
public interface Interceptor {
<T>T executor(Command<T> command);
Interceptor getInterceptor();
Interceptor next();
}
2、针对于这个接口,实现一个日志打印的责任链
public class LogInterceptor implements Interceptor{
private static Logger logger = LoggerFactory.getLogger(LogInterceptor.class);
private Interceptor next;
public LogInterceptor(Interceptor next){
this.next =next;
}
@Override
public <T>T executor(Command<T> command) {
if(logger.isDebugEnabled()){
logger.debug("command "+command.getClass().getSimpleName()+" is start !");
}
try{
return (T) this.next.executor(command);
}finally {
if(logger.isDebugEnabled()){
logger.debug("command "+command.getClass().getSimpleName()+" is finish! ");
}
}
}
@Override
public Interceptor getInterceptor() {
return this;
}
@Override
public Interceptor next() {
return next;
}
}
3、继续针对这个接口实现一个最终执行的责任链
public class RevokeInterceptor implements Interceptor{
public static Logger logger = LoggerFactory.getLogger(RevokeInterceptor.class);
private DataContext context;
public DataContext getContext() {
return context;
}
public void setContext(DataContext context) {
this.context = context;
}
@Override
public <T> T executor(Command<T> command) {
if(logger.isDebugEnabled()){
logger.debug(" command "+command.getClass().getSimpleName()+" is running! ");
}
return command.executor(context);
}
@Override
public Interceptor getInterceptor() {
return this;
}
@Override
public Interceptor next() {
throw new UnsupportedOperationException("bigdata no support!");
}
}
4、然后在Spring项目启动时,我们将责任链组合实例化到容器中。
@Configuration
public class BeanInit {
@Bean(name = "revokeInterceptor")
public RevokeInterceptor revokeInterceptor(){
return new RevokeInterceptor();
}
@Bean(name = "interceptor")
public Interceptor logInterceptor(RevokeInterceptor revokeInterceptor){
return new LogInterceptor(revokeInterceptor);
}
}
5、组装业务接口需要依赖的所有bean配置
@Component
@Order(2)
public class DataRunner implements ApplicationRunner {
@Resource
private ApplicationContext applicationContext;
@Override
public void run(ApplicationArguments args) throws Exception {
DataContext context = applicationContext.getBean(DataContext.class);
context.setDataMapper(applicationContext.getBean(DataMapper.class));
context.setDataService(applicationContext.getBean(DataService.class));
RevokeInterceptor revokeInterceptor = applicationContext.getBean(RevokeInterceptor.class);
revokeInterceptor.setContext(context);
}
}
6、编写BaseService类 包含责任链。
public class BaseService {
@Resource
protected DataContext context;
@Resource(name = "interceptor")
protected Interceptor commandExecutor;
}
7、编写Service, @DataModule 是对@Service注解的封装
我们将各个详细的实现放在一个个命令类中。
@DataModule
public class DataServiceImpl extends BaseService implements DataService {
@Override
public int addData(Data data) {
return this.commandExecutor.executor(new DataAddCommand(data));
}
@Override
public int addForUrl(String url) {
return this.commandExecutor.executor(new AddForUrlCommand(url));
}
@Override
public int addForUrl(String url, int iterator) {
return this.commandExecutor.executor(new AddForUrlCommand(url).setMaxIterator(iterator));
}
@Override
public List<Data> queryData(Data data) {
return context.getDataMapper().query(data);
}
@Override
public void dataToIndex(List<Data> data) {
this.commandExecutor.executor(new DataToIndexCommand(data));
}
@Override
public Result queryLucene(Result result) {
return this.commandExecutor.executor(new QueryLuceneCommand(result));
}
}
这样开发,使用责任链模式和命令模式结合,就可以将业务代码可以不断扩展,并且可以集中在指定的区域,开发起来更加优雅,并且可以保证代码的可读性和可维护性。