if-else嵌套太深?教你一个新手都能掌握的设计模式搞定!

云计算 虚拟化
不是什么地方都适合使用设计模式,如果逻辑简单,你硬要使用设计模式,只会带来结构上的复杂,大家可以按照大家的业务场景来使用。

[[321098]]

 我也不用设计模式

很多人觉得自己写的是业务代码,按照逻辑写下去,再把公用的方法抽出来复用就可以了,设计模式根本就没必要用,更没必要学。

一开始的时候,我也是这么想,直到我遇到。。。

举个栗子

我们先看一个普通的下单拦截接口。

基本逻辑,参数安全拦截,次数拦截,规则拦截,都通过,返回允许下单,任意一个失败,返回对应的失败原因。

多层嵌套if写法

我们正常多层嵌套if的写法

 

  1. /** 
  2.  * @author saier 
  3.  * @date 2020/3/31 18:03 
  4.  */ 
  5. public class Order { 
  6.     public Message interrupt1(){ 
  7.         return null
  8.     } 
  9.     public Message interrupt2(){ 
  10.         return null
  11.     } 
  12.     public Message interrupt3(){ 
  13.         return null
  14.     } 
  15.     public Message interrupt4(){ 
  16.         return null
  17.     } 
  18.     public Message interrupt5(){ 
  19.         return null
  20.     } 
  21.  
  22.     public static void main(String[] args) { 
  23.         Order order= new Order(); 
  24.         if(order.interrupt1().getResult() == 1){ 
  25.             if(order.interrupt2().getResult() == 1){ 
  26.                 if(order.interrupt3().getResult() == 1){ 
  27.                     if(order.interrupt4().getResult() == 1){ 
  28.                         if(order.interrupt5().getResult() == 1){ 
  29.                             System.out.println("success"); 
  30.                         } 
  31.                     } 
  32.                 } 
  33.             } 
  34.         } 
  35.  
  36.     } 
  37.  
  38. @Data 
  39. class Message { 
  40.     private int result; 
  41.     private String msg; 

异常处理逻辑

或者有些利用异常做逻辑,代码会简单一点

 

  1. /** 
  2.  * @author saier 
  3.  * @date 2020/3/31 18:03 
  4.  */ 
  5. public class Order2 { 
  6.     public void interrupt1(){ 
  7.  
  8.     } 
  9.     public void interrupt2(){ 
  10.  
  11.     } 
  12.     public void interrupt3(){ 
  13.         //失败 
  14.         throw new RuntimeException(); 
  15.     } 
  16.     public void interrupt4(){ 
  17.         //失败 
  18.         throw new RuntimeException(); 
  19.     } 
  20.     public void interrupt5(){ 
  21.         //失败 
  22.         throw new RuntimeException(); 
  23.     } 
  24.  
  25.     public static void main(String[] args) { 
  26.         Order2 order2= new Order2(); 
  27.         try{ 
  28.             order2.interrupt1(); 
  29.             order2.interrupt2(); 
  30.             order2.interrupt3(); 
  31.             order2.interrupt4(); 
  32.             order2.interrupt5(); 
  33.             System.out.println("success"); 
  34.         }catch (RuntimeException e){ 
  35.             System.out.println("fail"); 
  36.         } 
  37.  
  38.     } 

一开始,我就直接使用异常来做逻辑。但后续逻辑越来越复杂之后,也会出现一些问题。例如异常只能返回异常信息,不能返回更多的字段信息。

后面也留意到,异常做逻辑,在阿里规范是禁止的。

阿里代码规范 :

【强制】异常不要用来做流程控制,条件控制。

说明:异常设计的初衷是解决程序运行中的各种意外情况,且异常的处理效率比条件判断方式要低很多。

更重要的是,代码可读性太差了,随时一个方法的异常抛出来,还要考虑代码本身的异常。

没更好的办法,只能考虑设计模式了

怎么改,会使代码的可读性高,扩展性好?

在同事的提醒下,突然想起了设计模式!

我们希望达到的目的

  1. 代码没有这么多if else嵌套,可读性高
  2. 如果新增新的拦截逻辑简单方便,不影响原本的逻辑,扩展性好
  3. 可以很方便地调换拦截逻辑顺序,低耦合

责任链模式

在这种场景下,非常适合责任链模式。(什么场景使用什么设计模式,这就需要平时有积累,知道各种设计模式的基本使用)

责任链,顾名思义,就是用来处理相关事务责任的一条执行链,执行链上有多个节点,每个节点都有机会(条件匹配)处理请求事务,如果某个节点处理完了就可以根据实际业务需求传递给下一个节点继续处理或者返回处理完毕。

首先,建立过滤器的抽象类

 

  1. public abstract class AbstractFilter { 
  2.  
  3.     private AbstractFilter nextFilter; 
  4.  
  5.     /** 
  6.      * 责任链的下一个元素 
  7.      */ 
  8.     public void setNextFilter(AbstractFilter nextFilter){ 
  9.         this.nextFilter = nextFilter; 
  10.     } 
  11.  
  12.  
  13.     public AbstractFilter getLastFilter(){ 
  14.         if(this.nextFilter != null){ 
  15.             return this.nextFilter.getLastFilter(); 
  16.         }else
  17.             return this; 
  18.         } 
  19.     } 
  20.  
  21.     public void filter(FilterRequest filterRequest, Response response){ 
  22.         doFilter(filterRequest,response); 
  23.         if(response.isFilterNext() && nextFilter != null){ 
  24.             nextFilter.filter(filterRequest,response); 
  25.         } 
  26.     } 
  27.  
  28.     /** 
  29.      * 具体拦截逻辑 
  30.      */ 
  31.     public abstract void doFilter(FilterRequest filterRequest, Response response); 
  32.  
  33.     /** 
  34.      * 根据拦截结果做处理 
  35.      */ 
  36.     public void exec(FilterRequest filterRequest, Response response){ 
  37.     } 

过滤器的实现类

 

  1. @Component 
  2. @Order(5) 
  3. public class CheckParamFilter1 extends AbstractFilter { 
  4.     @Override 
  5.     public void doFilter(FilterRequest filterRequest, Response response) { 
  6.  
  7.     } 
  8.  
  9. @Component 
  10. @Order(10) 
  11. public class CheckParamFilter2 extends AbstractFilter { 
  12.     @Override 
  13.     public void doFilter(FilterRequest filterRequest, Response response) { 
  14.  
  15.     } 

使用Order注解,确定过滤器的顺序,后续在spring注入的时候,会有奇效

  1. //利用spring的自动注入机制 
  2. @Autowired 
  3. List<AbstractFilter> abstractFilterList; 
  4.  
  5. private AbstractFilter firstFilter; 
  6.  
  7. //spring注入后自动执行 
  8. @PostConstruct 
  9. public void initializeChainFilter(){ 
  10.     //把所有调用的逻辑注入到责任链,按照Order排序,越小优先级越高 
  11.     for(int i = 0;i<abstractFilterList.size();i++){ 
  12.         if(i == 0){ 
  13.             firstFilter = abstractFilterList.get(i); 
  14.         }else
  15.             firstFilter.getLastFilter().setNextFilter(abstractFilterList.get(i)); 
  16.         } 
  17.     } 
  18.  
  19. //直接使用 
  20. public Response exec(){ 
  21.     firstFilter.filter(filterRequest, response); 
  22.     return response; 

使用设计模式的好处

看下使用责任链模式后,有什么好处!

  1. 新增拦截逻辑,只需要再实现一个AbstractFilter类即可
  2. 修改拦截顺序,只需要修改Order注解的大小,越小,优先级越高
  3. 代码清晰,所有处理逻辑下沉到实现类中

使用设计模式的缺点

做到了低耦合,高扩展。但也带来了一些不好的地方

  1. 逻辑更复杂,用了链式等数据结构,要注意单例的问题,不能重复使用
  2. 类数量激增,一个拦截器就一个类

最后小结一下

不是什么地方都适合使用设计模式,如果逻辑简单,你硬要使用设计模式,只会带来结构上的复杂,大家可以按照大家的业务场景来使用。

关于作者:南山狮:理工男,7年互联网电商系统开发经验,知识分享领域探索小白。

责任编辑:武晓燕 来源: Hollis
相关推荐

2023-06-02 07:30:24

If-else结构流程控制

2022-07-11 08:16:55

策略模式if-else

2013-03-06 10:28:57

ifJava

2021-04-13 06:39:13

代码重构code

2021-03-10 07:20:43

if-else静态代码

2024-04-26 08:58:54

if-else代码JavaSpring

2021-11-04 08:53:00

if-else代码Java

2020-07-17 13:01:44

If-Else代码编程

2020-10-22 09:20:22

SQLNoSQL 数据库

2019-08-14 16:56:38

Python职责模式请假

2020-04-09 08:29:50

编程语言事件驱动

2020-04-30 09:17:28

数据分析电商分析思维

2020-06-04 09:18:52

CTOif-else代码

2022-01-13 10:45:59

if-else代码Java

2020-12-15 09:31:58

CTOif-else代码

2020-05-13 14:15:25

if-else代码前端

2020-12-29 09:16:36

程序员对象开发

2018-08-15 15:23:48

视频

2022-05-26 10:42:30

数据权限注解

2024-04-16 00:07:36

设计模式代理模式替身
点赞
收藏

51CTO技术栈公众号