作者 l 南山狮
本文经授权转载自Hollis(ID:hollischuang)
我也不用设计模式
很多人觉得自己写的是业务代码,按照逻辑写下去,再把公用的方法抽出来复用就可以了,设计模式根本就没必要用,更没必要学。
一开始的时候,我也是这么想,直到我遇到。。2 n / 9 I s .。
举个栗子e @ L Q @ s I
我们先看一个普通的下单拦截接口。
基本逻辑,参数安全拦截,次数拦截,规则拦截,都通过,返回允许下单,任意一个失败,返回对应的失败原因。
多层嵌套if写法
我们正常多层嵌套if的写法
/**
* @author saier
* @date 2I ; ! ) K b j O020/3/31 18:03
*/
public class Order {
public Message interrupt1{
return ;
}
public Message interrupt2{
return ;
}
p_ = Y ~ ` v G Rublic Message interrupt3{
return ;
}
public Message interrupt4{t m = # & A D k y
return ;
}
public Message interrupt5{
return ;
}
public static void main(String[] args) {
Order order= new Order;
if(order.interrupt1.getRE ~ ;esult == 1){
if(order.interrupt2.u R a T ,getResult == 1){
if(order.interrupt3.getResult == 1){
if(order.interrupt4.getResult == 1){
if(order.interrupt5.getResult == 1){
System.out.println(\"success\");
}
}
}
}
}
}
}
@Data
class Message {
private int result;
privl s rate String msg;
}
异常处理逻辑
或者有些利用异常做逻辑,代码会简单一点
/**
* @author saiera L * X
* @date 2020/3/31 18:03
*/
public classo T W j z P Order2 {
public void interrupt1{
}
public void interrupt2{
}
pr + p + z Mublic void interrupt3{
//失败
throw new RuntimeException;
}
public voJ 2 s ( 6 Oid interrupt4{
/l + * (/失败
throw new RuntE ` ~ 3 j a JimeException;
}
public void interrupt5{
//失败
throwC G x Q 9 2 . + D new RuntimeException;
}
public static voiC 2 E } , t |d main(String[] args) {
Order2 order2= new1 w z 5 + l Order2;
try{
order2.inter6 w ] t , 6 m zrupt1;
order2.interrupt2;
order2.interrupt3;
ora ^ ( { V Uder2.interrupt4;
orde0 y rr2.interrupt5;
System.out.println(\"success\");
}catch ($ E 5 P s O R 8 [RuntimeException e){B | {
System.out.println(\"fail\");
}
}
}
一开始,我就直+ W F V h ^ h接使用异常来做逻辑。但后续逻辑越来越复杂之后,也会出现一些问题。例如异常只能返回异常信息! H t a 8 ,,不能返回更多的字段信息。
后面也留意到,异常做逻辑,在阿里规范是禁止的。
阿里代码规范 :
【强制】异常不要用来做流程控制,条件控制。
说明:异常设计的初衷是解决程序运行中的各种意外情况,且异常的处理效率比条件判断方式要低很多。
更重要的是,代码可读性太差了,随时一个z k 方法的异常抛出来,还要考虑代码本身的异常。
没更好的办法,只能考虑设计模式了
怎么改,会使代码的可读性高,扩展性好?
在同事的提醒下,突然想起了设计模式!
我们希望达到的目的
-
代码没有这么多if else嵌套,可读性高
-
如果新增新的拦截逻9 * g v : l辑简单方便,不影响原P T 4本的逻辑,扩展性好
-
可以很方便地调换拦截逻辑顺序,低耦合
责任链模式
在这种场, C 3 # 景下,非常适合责任链模式。(什么场景使用什么设计模式,这就需要平时有积累,知道各种} F B U M设计模式的基本使用)
责任链,顾名思义,就是用来处理相关事务责任的一条执行链,执行链上有多个节点,每个节点都有机会(条B v B g A Y k @ }件匹配)处理请求事务,如果某个节点处理完了就可以根据实际业务需求传递给下一个节点继续处理或者返回处理完毕。
首先,建立过滤器的抽象类
publi. - Kc abstract class AbstractFm j 7 7 3 ( ~ kilter {
private AbstractFilter nextFilter;
/**
* 责任链的下一个元素
*/
public void setNextFilter(AbstractFilter nextFilter){
this.nextFilter = nextFilter;
}E z - M L d $
public AbstractFilter getLz ) = ( * v @ 9 TastFilter{
i7 x 3 o X w t !f(this.nex9 4 | 6 =tFilt{ R 9 P ter != ){
return this.nextS H %Filter.g= - $ Aet; I Y [ ( % * qLastFilter;
}else{
retF y Nurn thv ( # . v a ~ y ^is;
}
}
public void filter(FilterRequest filterRequest, Response response){
doFilter(filterRequest,response);
if(response.isFilterNext && nextFilter != ){
nextFilter.filt; ] g W _er(filterRequest,response);
}
}
/**
* 具体拦截逻辑
*/
public abstract void doFilter(FilterRequest filterRequest, Response response);
/**
* 根据拦截结果做处理
*/
public void exec(FilterRequest filterRequest, Response response){
}
}
过滤器的实现类:
@Component
@Order(5)
pubA F [ E h Ylic class Chw w F 4 Y HeckParamFilter1 extends AbstractFilter {
@Override
publiU A G = g Q 3 7c void doFilter(FilterRequest filterRequest, Response response= H c 6 l i , u) {
}
}
@Component
@Order(10)
public class Checg S Y h S *kParamFilter2 extends AbstractFilter {
@Override
puN - q e Lblic void doFilter(FilterRequest filterRequest, Response response) {
}
}
使用Order注U H (解,确L H u | u | 5 [定过滤器的顺序,后续在spring注入的时候,会有奇效
//利用spring的自动注入g p h p K K 8 8机制
@Autowired
List<AbstractFilto - : + . ger> abstractFilterList;
private Absa } * ~ z = etractFilter firstFilter;
//spring注入后自动执行
@1 d V o 3PostConsv O ~ 3 8 [ 7 i +truct
public void initializeChainFilter{
//把所有调用的逻辑注b : f C 3入到责任链,按照Order排序,越小c & : H优先级越高
for(int i = 0;i<5 s t [ D D b aabstractFilterLc m Xist.size;i++){
if(i == 0){
firsty 0 YFilter = abstractFilterList.get(i);
}elsC : w l % y me{
firstFilter.getLastFilter.setNexty i MFilter(abstractFilterList.get(i));
}
}
}
//直接使用
public Response exec{
firstFilter.filter(filterRequest, response);
return response;
}
使用设计模式的好处
看下I , S 2 . B使用责任链模式后( S I 0 w z,有什么好处!
-
新增拦截逻辑,只需要再实现一个AbstractFilter类即可
-
修改拦截顺序,只需要修改Order注b d } / ^ 0解的大小,越小,优先级越高
-
代码清晰,所m y 0 g j ,有处理逻辑下沉到实现类中
使用设计模式的缺点S 0 W
做到了低耦合,高扩展。但也带来了一些不好的地方
-
逻辑更复杂,用了链式等数据结构,要注意单例的问题,不能重复使用
-
类数量激增,一个拦截器就一个类! w b ] 9 9 = q (
最后小结一下
不是什C W ~ |么地方都适合使用设计模式,如果逻辑简单,你硬要使用设计模式,只会带来结构上的复杂T $ V w =,大家可以按照大家的业务场景来使 # C & ) r ^ + ?用。
作者简介:南山狮,理工男,7年互联网电商系统开发经验,知识分享领域探索小白。M 1 _ % | 6 5 }公众号:互联网编程,白话文帮助你了解编程。
☞程序员职场背锅甩锅指南
☞“H@ H | . Y } m iey Siri” 背后的黑科技大揭秘!
☞红外光抗疫、成功预测新基建,投c ^ 4 D资 280 家企业的光学N $ [博士到底是谁?
☞如何做一名 q H M s H V出色的初级开发?
☞半小时训练亿级规模知识图谱,亚1 S p R + g ^马逊AI开源知识图谱嵌入表示框架D= 1 [ c B x i UGLq p W X-KE
☞警惕!新骗术出现:这些虚X 3 ! k N m n假二维码生成器已成功盗取 4.6 万美元!
☞“出道” 5 年采用率达 78%,KuberneK T Stes 的成功秘0 $ o * y C 9 O z诀是什么?