共计 3369 个字符,预计需要花费 9 分钟才能阅读完成。
所有抛开业务的设计,都是扯淡!在我的项目中有个咱们会对多个接口进行多业务逻辑判断,我的项目开始工期紧,所以先以实现性能为主,最近打算优化一番,一开始的代码是这样的
public void checkProjectAdd(List<OrderDetail> list) {if (!CollectionUtils.isEmpty(list)) {orderService.check(list);
stockService.check(list);
orderAddress.check(list);
userScoreService.check(list);
activityService.check(list);
this.check();}
excute();}
尽管对查看类的办法做了简略的封装,但在好多中央可能会存在反复的判断,比方订单提交,退出购物车等等,冗余代码随处可见,且不易扩大。在此情景下,废话不多说,筹备开干,先来剖析剖析业务,因为咱们的各个查看接口的解决准则是要保障程序性的,而在查看的过程中可能依据商品提交参数而本质去动静扭转 list 参数中的内容,比方一个库存当两个卖,用户会员等级结合实际商品数判断是否享受折扣等等,所以每一级的查看或手动解决值都是要求查看类代码 执行程序,思前想后,想起曾在浏览 mybatis 源码时感觉其设计的 plugins 模式很适宜此类场景,于是决定应用《责任链模式》来进行这一次代码的优化。
首先简略介绍一下什么是责任链,说到链,大家就能想到链表,这里咱们只说最简略的链表(单向链表)
单向链表就是以后对象内存储着下一个对象的援用地址,责任链模式的概念也形容下:
责任链模式(Chain of Responsibility Pattern)为申请创立了一个接收者对象的链。这种模式给予申请的类型,对申请的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。在这种模式中,通常每个接收者都蕴含对另一个接收者的援用。如果一个对象不能解决该申请,那么它会把雷同的申请传给下一个接收者,依此类推。
** 概念都是规范,个别都很难了解是什么意思,咱们拿图说事
**
这每一层都是大哥,想要跨过难关还是不太容易呀。然而没方法为了要干真正的实事还是要一关一关闯的,接下来咱们要开始进行包装,AOP 大家都晓得(面向切面),既然咱们最终的提交办法是 excute,那切面就是 excute 了,在切面之前如何执行自定义的 Interceptor(拦截器)呢?这里我是用的是 jdk 动静代理模式,动静代理,不太理解的看这里(JDK 动静代理),应用动静代理的益处是咱们能够对成千盈百个已知与未来可能要编写的接口进行包装,比方我的订单提交事件叫做 submitOrder,退出购车 addCart,我都能够通过我的代理模式对这些接口进行包装,在代理模式中我规定好 Interceptor,这样就能对立了
通过一级一级的代理模型,最终咱们能力真正调用到 IOrderService 的具体实现上,废话不多说,开始撸代码
首先定义好咱们本人拦截器类
public interface Interceptor {Object intercept(Invocation invocation) throws InvocationTargetException, IllegalAccessException;
}
接下来代理工厂:
public class ProxyFactory implements InvocationHandler {
private Object target;
private Interceptor interceptor;
private ProxyFactory(Object target, Interceptor interceptor) {
this.target = target;
this.interceptor = interceptor;
}
public static Object wrap(Object target, Interceptor filter) {ProxyFactory proxyFactory = new ProxyFactory(target, filter);
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), proxyFactory);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Invocation invocation = new Invocation(target, method, args);
return interceptor.intercept(invocation);
}
}
代理工厂次要就是对指标对象 target 进行包装,这里的 target 可能是原对象,也有可能是包装过后代理对象二次包装代理,简略来说是这样,咱们的 IOrderService 中的 submitOrder 办法,在托管给 JDK 动静代理后,为了实现责任链的链式准则,咱们会基于此对象再次调用 wrap 办法进行二次包装,将咱们的各式各样的拦截器一层一层的包装下来,这样解决成上一级援用下一级的链式关系。
接下来定义咱们具体都又那些拦截器大哥
public class TodoInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws InvocationTargetException, IllegalAccessException {System.out.println("todo something");
Object result = invocation.proceed();
System.out.println("to do end something");
return result;
}
}
public class LogInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws InvocationTargetException, IllegalAccessException {System.out.println("do log");
Object result = invocation.proceed();
System.out.println("do log");
return result;
}
}
两位拦路大哥已再此,接下来咱们吧拦路大哥们放入工厂进行包装
@Override
public void checkSubmitOrder() {IOrderService orderService = new OrderService();
orderService = (IOrderService) ProxyFactory.wrap(orderService, new LogInterceptor());
orderService = (IOrderService) ProxyFactory.wrap(orderService, new TodoInterceptor());
orderService.submitOrder();}
代码执行成果如下
例子挺简略的,次要是阐明责任链能够应用的场景,联合此责任链的扩大就十分多了,例如我把拦截器对立交给 spring 托管,在每个查看办法上自定义注解,标记须要执行的拦截器,在 AOP 切面扫描业务办法时,判断是否存在此类责任链的拦挡注解,有的话则执行业务判断,这样子就对立了业务查看代码的封装,再也不必再每行代码里写那些反复的 chek()了,介于篇幅,就不在过多介绍了,有趣味能够私聊我。
起源:https://www.cnblogs.com/doNet…
欢送关注公众号【码农开花】一起学习成长
我会始终分享 Java 干货,也会分享收费的学习材料课程和面试宝典
回复:【计算机】【设计模式】【面试】有惊喜哦