△Hollis, 一个对Coding有着独特追求的人△

这是Hollis的第 259篇原创分享

作者 l 南山狮

来源 l Hollis(ID:hollischuang)

我也不用设计模式

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

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

举个栗子

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

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

多层嵌套if写法

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

/*** @author saier* @date 2020/3/31 18:03*/
public class Order {public Message interrupt1(){return null;}public Message interrupt2(){return null;}public Message interrupt3(){return null;}public Message interrupt4(){return null;}public Message interrupt5(){return null;}public static void main(String[] args) {Order order= new Order();if(order.interrupt1().getResult() == 1){if(order.interrupt2().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;private String msg;
}

异常处理逻辑

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

/*** @author saier* @date 2020/3/31 18:03*/
public class Order2 {public void interrupt1(){}public void interrupt2(){}public void interrupt3(){//失败throw new RuntimeException();}public void interrupt4(){//失败throw new RuntimeException();}public void interrupt5(){//失败throw new RuntimeException();}public static void main(String[] args) {Order2 order2= new Order2();try{order2.interrupt1();order2.interrupt2();order2.interrupt3();order2.interrupt4();order2.interrupt5();System.out.println("success");}catch (RuntimeException e){System.out.println("fail");}}
}

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

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

阿里代码规范 :
【强制】异常不要用来做流程控制,条件控制。
说明:异常设计的初衷是解决程序运行中的各种意外情况,且异常的处理效率比条件判断方式要低很多。

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

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

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

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

我们希望达到的目的

  1. 代码没有这么多if else嵌套,可读性高

  2. 如果新增新的拦截逻辑简单方便,不影响原本的逻辑,扩展性好

  3. 可以很方便地调换拦截逻辑顺序,低耦合

责任链模式

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

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

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

public abstract class AbstractFilter {private AbstractFilter nextFilter;/*** 责任链的下一个元素*/public void setNextFilter(AbstractFilter nextFilter){this.nextFilter = nextFilter;}public AbstractFilter getLastFilter(){if(this.nextFilter != null){return this.nextFilter.getLastFilter();}else{return this;}}public void filter(FilterRequest filterRequest, Response response){doFilter(filterRequest,response);if(response.isFilterNext() && nextFilter != null){nextFilter.filter(filterRequest,response);}}/*** 具体拦截逻辑*/public abstract void doFilter(FilterRequest filterRequest, Response response);/*** 根据拦截结果做处理*/public void exec(FilterRequest filterRequest, Response response){}
}

过滤器的实现类

@Component
@Order(5)
public class CheckParamFilter1 extends AbstractFilter {@Overridepublic void doFilter(FilterRequest filterRequest, Response response) {}
}@Component
@Order(10)
public class CheckParamFilter2 extends AbstractFilter {@Overridepublic void doFilter(FilterRequest filterRequest, Response response) {}
}

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

//利用spring的自动注入机制
@Autowired
List<AbstractFilter> abstractFilterList;private AbstractFilter firstFilter;//spring注入后自动执行
@PostConstruct
public void initializeChainFilter(){//把所有调用的逻辑注入到责任链,按照Order排序,越小优先级越高for(int i = 0;i<abstractFilterList.size();i++){if(i == 0){firstFilter = abstractFilterList.get(i);}else{firstFilter.getLastFilter().setNextFilter(abstractFilterList.get(i));}}
}//直接使用
public Response exec(){firstFilter.filter(filterRequest, response);return response;
}

使用设计模式的好处

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

  1. 新增拦截逻辑,只需要再实现一个AbstractFilter类即可

  2. 修改拦截顺序,只需要修改Order注解的大小,越小,优先级越高

  3. 代码清晰,所有处理逻辑下沉到实现类中

使用设计模式的缺点

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

  1. 逻辑更复杂,用了链式等数据结构,要注意单例的问题,不能重复使用

  2. 类数量激增,一个拦截器就一个类

最后小结一下

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

关于作者南山狮:理工男,7年互联网电商系统开发经验,知识分享领域探索小白。公众号:互联网编程,白话文帮助你了解编程。


Java工程师成神之路系列文章在 GitHub 更新中,欢迎关注,欢迎star。 直面Java第305期:TLAB带来的问题?深入并发第013期:拓展synchronized——锁优化
- MORE | 更多精彩文章 -前端大神的离逝,让我们不得不有所反思。
我,程序员,32岁,距离退休,只剩3年了!
99%的程序员都在用Lombok,原理竟然这么简单?我也手撸了一个!
一个Java多线程的问题,颠覆了我多年的认知!
如果你喜欢本文,请长按二维码,关注 Hollis.转发至朋友圈,是对我最大的支持。好文章,我在看❤️

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

  1. while循环里嵌套一个if_if-else嵌套太深?教你一个新手都能掌握的设计模式搞定!...

    作者:南山狮 来自:Hollis 我也不用设计模式 很多人觉得自己写的是业务代码,按照逻辑写下去,再把公用的方法抽出来复用就可以了,设计模式根本就没必要用,更没必要学. 一开始的时候,我也是这么想,直 ...

  2. 域嵌套太深_pyspark如何修改嵌套结构域

    域嵌套太深 In our adventures trying to build a data lake, we are using dynamically generated spark cluste ...

  3. Word 域嵌套太深弹窗,更新域卡顿,解决办法

    1.问题描述 用Word编辑几百页或者上千页的文档时,因为资料来源和拷贝的关系,总会遇到各种有问题的文档块,一般更新目录页码或者题注序号时,最快的操作就是CTRL+A,然后F9,但是偶尔会遇到这样的文 ...

  4. 教你一招超级简单的方法快速搞定grub.conf文件的丢失及损坏

    教你一招超级简单的方法快速搞定grub.conf文件的丢失及损坏 实验环境: GRUB是大多数Linux系统默认使用的引导程序,当"/boot/grub/grub.conf"配置文 ...

  5. iframe标签中写html,html页面中嵌套iframe标签,我们可以用html中的iframe标签搞定

    iframe嵌入网页的用法 iframe并不是很常用的,在标准的网页中非常少用.但是有朋友经常问到,下面我简单地介绍一下它的用法,你只要熟练掌握这些参数足矣. 也应该是框架的一种形式,它与不 ...

  6. 如何解决代码嵌套太深问题

    $.ajax({success: function () {$.ajax({success: function () {$.ajax({success: function () {complete() ...

  7. 代码的坏味道:控制结构嵌套太深

    重构前的代码 def newPrj(self,db,userId,prjName,password,privacy,intro='',status='active'): s = '' flag = F ...

  8. python 如何判断一个函数执行完成_三步搞定 Python 中的文件操作

    当程序运行时,变量是保存数据的好方法,但变量.序列以及对象中存储的数据是暂时的,程序结束后就会丢失,如果希望程序结束后数据仍然保持,就需要将数据保存到文件中. Python 提供了内置的文件对象,以及 ...

  9. 还在因常常忘记关电脑而烦恼吗?小编教你一招,一封邮件轻轻松松搞定

    原标题:运用Python爬虫实现远程控制电脑关机 在大一时,我们老师教过我们远程电脑关机,但那个代码比较多,而且我也没有实现.现在,通过这个寒假学习Python爬虫,实现这个过程好像变得非常简单了. ...

最新文章

  1. 用 Jackson 来处理 JSON
  2. docker 创建启用systemd服务的容器
  3. DPDK — 网卡初始化流程(Intel 82599 ixgbe 网卡驱动示例)
  4. SASS type-of 函数
  5. 【云计算 Hadoop】Hadoop 版本 生态圈 MapReduce模型
  6. [C/CPP系列知识] Type difference of character literals 和 bool in C and C++
  7. 埃及分数The Rotation Game骑士精神——IDA*
  8. 201571030316/201571030314 《小学四则运算练习软件需求说明》结对项目报告
  9. iLogtail使用入门-iLogtail本地配置模式部署(For Kafka Flusher)
  10. 5张图看懂如何实现Windows RTMP实时导播功能
  11. [Swift]LeetCode289. 生命游戏 | Game of Life
  12. python对于设计师有什么用-Python前程无忧深圳UI设计师岗位分析
  13. 深度学习实战之手写签名识别(100%准确率、语音播报)
  14. python logisticregression_Python机器学习sklearn LogisticRegression用户流失预测模型初探
  15. PostgreSQL 10.1 手册_部分 III. 服务器管理_第 28 章 监控数据库活动_28.3. 查看锁
  16. 个人财务管理系统mysql_个人财务管理系统功能模块设计
  17. matlab 光斑质心算法,高精度光斑中心定位算法
  18. P1296 分形宇宙
  19. python实现企业微信定时发送文本消息
  20. winUSB设备的开发方法

热门文章

  1. java合并多个表格为一个_多个DataTable的合并成一个新表
  2. php open gl,Open GL 资料 01
  3. Python中使用中文
  4. Java版单链表讲解
  5. LeetCode 138 复制带随机指针的链表
  6. USACO Section 1.2 Greedy Gift Givers (简单查找)
  7. 编译原理中LL(1)分析程序的设计---用c++程序语言实现
  8. Ubuntu 18.04-20.04开机自动root用户登录(测试可用)
  9. BZOJ2759 一个动态树好题
  10. Gym 101128A :Promotions (Southwestern Europe Regional Contest )