while循环里嵌套一个if_if-else嵌套太深?教你一个新手都能掌握的设计模式搞定!...
作者:南山狮 来自:Hollis
我也不用设计模式
很多人觉得自己写的是业务代码,按照逻辑写下去,再把公用的方法抽出来复用就可以了,设计模式根本就没必要用,更没必要学。
一开始的时候,我也是这么想,直到我遇到。。。
举个栗子
我们先看一个普通的下单拦截接口。
基本逻辑,参数安全拦截,次数拦截,规则拦截,都通过,返回允许下单,任意一个失败,返回对应的失败原因。
多层嵌套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"); } } } } } }}@Dataclass 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"); } }}
一开始,我就直接使用异常来做逻辑。但后续逻辑越来越复杂之后,也会出现一些问题。例如异常只能返回异常信息,不能返回更多的字段信息。
后面也留意到,异常做逻辑,在阿里规范是禁止的。
阿里代码规范 :
【强制】异常不要用来做流程控制,条件控制。
说明:异常设计的初衷是解决程序运行中的各种意外情况,且异常的处理效率比条件判断方式要低很多。
更重要的是,代码可读性太差了,随时一个方法的异常抛出来,还要考虑代码本身的异常。
没更好的办法,只能考虑设计模式了
怎么改,会使代码的可读性高,扩展性好?
在同事的提醒下,突然想起了设计模式!
我们希望达到的目的
- 代码没有这么多if else嵌套,可读性高
- 如果新增新的拦截逻辑简单方便,不影响原本的逻辑,扩展性好
- 可以很方便地调换拦截逻辑顺序,低耦合
责任链模式
在这种场景下,非常适合责任链模式。(什么场景使用什么设计模式,这就需要平时有积累,知道各种设计模式的基本使用)
责任链,顾名思义,就是用来处理相关事务责任的一条执行链,执行链上有多个节点,每个节点都有机会(条件匹配)处理请求事务,如果某个节点处理完了就可以根据实际业务需求传递给下一个节点继续处理或者返回处理完毕。
首先,建立过滤器的抽象类
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 { @Override public void doFilter(FilterRequest filterRequest, Response response) { }}@Component@Order(10)public class CheckParamFilter2 extends AbstractFilter { @Override public void doFilter(FilterRequest filterRequest, Response response) { }}
使用Order注解,确定过滤器的顺序,后续在spring注入的时候,会有奇效
//利用spring的自动注入机制@AutowiredList abstractFilterList;private AbstractFilter firstFilter;//spring注入后自动执行@PostConstructpublic void initializeChainFilter(){ //把所有调用的逻辑注入到责任链,按照Order排序,越小优先级越高 for(int i = 0;i
使用设计模式的好处
看下使用责任链模式后,有什么好处!
- 新增拦截逻辑,只需要再实现一个AbstractFilter类即可
- 修改拦截顺序,只需要修改Order注解的大小,越小,优先级越高
- 代码清晰,所有处理逻辑下沉到实现类中
使用设计模式的缺点
做到了低耦合,高扩展。但也带来了一些不好的地方
- 逻辑更复杂,用了链式等数据结构,要注意单例的问题,不能重复使用
- 类数量激增,一个拦截器就一个类
最后小结一下
不是什么地方都适合使用设计模式,如果逻辑简单,你硬要使用设计模式,只会带来结构上的复杂,大家可以按照大家的业务场景来使用。
while循环里嵌套一个if_if-else嵌套太深?教你一个新手都能掌握的设计模式搞定!...相关推荐
- if-else嵌套太深?教你一个新手都能掌握的设计模式搞定!
△Hollis, 一个对Coding有着独特追求的人△ 这是Hollis的第 259篇原创分享 作者 l 南山狮 来源 l Hollis(ID:hollischuang) 我也不用设计模式 很多人觉得 ...
- 微信/易信公共平台开发(一):开发了一个简单易用的PHP类(提供源码),十几行代码搞定一个公众号
这两天学习了一下微信公共平台和易信公共平台的开发 (易信与微信协议是基本一样的)(PS:没听说过易信?你out了?) 公共平台开发原理这里就不讲了,如果是初次接触的同学,建议先看 David_Tang ...
- 如何剪辑一个好的短视频?教你一个小技巧,剪辑视频很简单
短视频现在越来越受到大众喜欢,不管是老人.小孩.年轻人都会在有空余时间刷下短视频,不知不觉得短视频已形成人们平时生活中一部分,那么要如何剪辑一个好的短视频,制作短视频可以分成两个部分:第一部分就是选题 ...
- php循环26个英文字母,有趣的真人字母操,形象生动容易学,帮孩子瞬间搞定26个英文字母,效果满分!...
Alligator 鳄鱼.Ant 蚂蚁.Apple 苹果; Bear 熊.Bird 鸟.Bubble 气泡; Cow 奶牛.car 小汽车.clap 鼓掌; Dog 狗.Donut 甜圈圈.Drum ...
- python防反编译_用Python和Smali模拟器搞定一个加混淆、防篡改的APK逆向
这个周末我和好友聊天时,他向我求助修改一个他正在编写Python脚本.他试图通过解混淆一个APK,来理解该APK的混淆基址和防篡改保护机制.同我以往的APK逆向过程(dex2jar->jd-gu ...
- 200行代码搞定一个购物网站+电影站+APP
以前有一个朋友问我,说想做一个购物网站 ,电影站 ,需要APP 形式提供 . 问我一个星期能不能搞定,听了他的奇葩需求后,有点被耍的感觉,在普通人眼里 一个程序可能就是半天就做出来的东西. 后来仔细想 ...
- python中一个对象只能被一个变量引用吗_Python中for循环里的变量无法被引用的解决方法...
在之前的编程语言里,学到for循环里面是可以重置变量i的值的,然后让整个for循环从头开始,但是在python里面却行不通这是为什么呢? 在python中,for循环相当于一个迭代器(Iterator ...
- 根据上面的products列表写一个循环,不断询问用户想买什么,用户选择一个商品编号,就把对应的商品添加到购物车里,终用户输入q退出时,打印购买的商品列表。
一.问题: 现有商品列表如下: 1.products = [["iphone",6888],["MacPro",14800],["小米6", ...
- Repeater 嵌套 绑定数据,嵌套的Repeater无法绑定的问题
Repeater 嵌套 绑定数据,嵌套的Repeater无法绑定的问题 今天做绑定遇到了这个么个问题,绑定的事件ItemDataBound()跟之前的并没有 改动,为什么会出现绑定失败的问题呢?要是你 ...
最新文章
- layout-maxWidth属性用法
- 如何使用ping命令检查网络故障
- DEV-C++调试设置
- 科技公司如何占据了你的每一分钟?
- Hexo瞎折腾系列(6) - 将博客同时部署到Github和Coding
- ArcGIS快速制图插件介绍
- 在XNA 3.0 项目添加声音——通过Xact播放简单的.wav文件
- POJ1149PIGS
- SpringBoot 实战 (二) | 第一个 SpringBoot 工程详解
- mysql case结合group+having使用
- 宝塔 python项目管理器2.0 部署django项目 uwsgi
- 机器视觉运动控制一体机应用例程|芯片引脚缺陷检测系统
- 安卓(Android)的原生系统真的那么好用吗
- 【计算机组成与结构】中央处理器
- CondaUpgradeError: This environment has previously been operated on by a conda version that‘s newer
- 【怎么突破安全狗和360网站卫士的】
- 啥? 代码可以改变世界? 道翰天琼认知智能API接口平台为您揭秘。
- c语言无符号整型除法,用位运算的方法实现无符号整数的除法,游戏编程 | 李大仁博客...
- mysql 空集 赋值,mysql – 是否有一个简单的SELECT-Statement创建一个空集?
- HDU 献给杭电五十周年校庆的礼物
热门文章
- how to consume a webservice via ABAP proxy
- Total = 80是这样计算出来的
- 如何使用Java keytool命令行创建一个自签名证书
- 面试问题 - 只用位操作在ABAP里实现a+b
- ICEM特别卡顿,NVIDIA英伟达显卡问题,将集成处理器改成高性能即可【终极解决方案】
- numpy不用科学记数发 python_Python科学计算库Numpy常用的函数使用
- python 月活_TikTok用户月活超1亿意味着什么?什么是月活用户?
- 圆周移位是怎么移的_想烟道移位,师傅却连连摆手:小区烟道都是统一的,咋能随便改...
- windows下写代码在linux下编译,如何在Windows中编译Linux Unix的代码(采用cygwin)?...
- mysql 开启innodb win版本_MySQL安装与启动——Windows系统下