谁能干掉了if else
很多人觉得自己写的是业务代码,按照逻辑写下去,再把公用的方法抽出来复用就可以了,设计模式根本就没必要用,更没必要学。
一开始的时候,我也是这么想,直到我遇到。。。
举个例子
我们先看一个普通的下单拦截接口。
基本逻辑,参数安全拦截,次数拦截,规则拦截,都通过,返回允许下单,任意一个失败,返回对应的失败原因。
多层嵌套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");
}
}
}
一开始,我就直接使用异常来做逻辑。但后续逻辑越来越复杂之后,也会出现一些问题。例如异常只能返回异常信息,不能返回更多的字段信息。
后面也留意到,异常做逻辑,在阿里规范是禁止的。
阿里代码规范 :
【强制】异常不要用来做流程控制,条件控制。
说明:异常设计的初衷是解决程序运行中的各种意外情况,且异常的处理效率比条件判断方式要低很多。
更重要的是,代码可读性太差了,随时一个方法的异常抛出来,还要考虑代码本身的异常。
没更好的办法,只能考虑设计模式了
怎么改,会使代码的可读性高,扩展性好?
在同事的提醒下,突然想起了设计模式!
我们希望达到的目的
- 代码没有这么多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的自动注入机制
@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;
}
使用设计模式的好处
看下使用责任链模式后,有什么好处!
- 新增拦截逻辑,只需要再实现一个AbstractFilter类即可
- 修改拦截顺序,只需要修改Order注解的大小,越小,优先级越高
- 代码清晰,所有处理逻辑下沉到实现类中
使用设计模式的缺点
做到了低耦合,高扩展。但也带来了一些不好的地方
- 逻辑更复杂,用了链式等数据结构,要注意单例的问题,不能重复使用
- 类数量激增,一个拦截器就一个类
最后小结一下
不是什么地方都适合使用设计模式,如果逻辑简单,你硬要使用设计模式,只会带来结构上的复杂,大家可以按照大家的业务场景来使用。
谁能干掉了if else的更多相关文章
- 干掉命令行窗口下MySql乱码
晚上重温dos窗口操作mysql的时候,遇到了一个巨蛋疼的问题------>中文验证码 -->_-->,所以找了找资料弄懂了怎么解决乱码问题,,小记一下. 新建一个表 create ...
- 干掉Unity3D
我为什么想干掉Unity3D? 这个问题容我不答,每个做技术的人总有一些完美主义. 你使用u3d的过程中是不是痛并快乐着呢. 就从两个国内具有相当普遍性的痛点说起. il2cpp,unity作出了这个 ...
- Markdown会干掉Html吗?
Markdown会干掉Html吗? 很明显,MarkDown正在已一种比病毒还快的速度传播着,量子的机器人语言也是深受其启发,当然了,在这个东西没搞出来之前,MarkDown就能干很多事情,比如在线编 ...
- Excel应该这么玩——1、命名单元格:干掉常数
命名单元格:通过名称来引用单元格中的值,常用于引用固定不变的值. 单元格是Excel中存储数据的最小单位,在公式中通过A1.B2之类的名称来引用其中的值.A1只是单元格的坐标,就好像人的身份证号.生活 ...
- 夺命雷公狗---DEDECMS----8dedecms干掉首页和-文档页-栏目页的页面的广告
我们首先来将首页生成静态页面,如下图所示: 成功后,如下显示: 如果成功后则在文件夹下多了一个index.html的文件.. 我们的首页静态页面是通过模版文件生成,所以我们只需要把模版文件的广告标签删 ...
- 干掉cmd:windows下使用linux命令行
对于喜欢用命令行的朋友们,在windows下面使用cmd窗口是不是很不爽?复制不方便?不能随意放大缩小?如果需要多个控制台要多个窗口?....各种不爽 一.基础工具 如果你也不爽,那就对了,所以给大家 ...
- Linux中 干掉原来的PHP方法
干掉原来的PHP方法: 查看php版本命令:#php -v这个命令是删除不干净的#yum remove php因为使用这个命令以后再用#php -v还是会看到有版本信息的..... 必须强制删除#rp ...
- Xcode6为什么干掉pch(Precompile Prefix Header)&如何添加pch文件
转载: http://blog.csdn.net/iosdevtip/article/details/40918353 一直在用xcode6开发,但项目都是在xcode5上创建的,所以一直没注意到, ...
- Xcode6为什么干掉pch(Precompile Prefix Header)&怎样加入pch文件
一直在用xcode6开发,但项目都是在xcode5上创建的,所以一直没注意到,xcode6居然干掉pch文件了. 为什么xcode6没有自己主动创建pch文件呢? 简单地看:我们在写项目的时候,大部分 ...
- 使用gc、objgraph干掉python内存泄露与循环引用!
Python使用引用计数和垃圾回收来做内存管理,前面也写过一遍文章<Python内存优化>,介绍了在python中,如何profile内存使用情况,并做出相应的优化.本文介绍两个更致命的问 ...
随机推荐
- 剖析XAML语言
这节剖析一下XAML(读作:zaml)--这一WPF中的UI设计语言. XAML 在wpf中,UI部分使用xaml语言来编写,xaml语言是由xml语言派生而来的语言,所以在xaml中我们可以看到很多 ...
- VS2017报错 由#define后的分号引发的【“ 应输入“)】
其实并不是第十行分号出现了问题,而是由于在宏定义后面加了分号,修改成这样即可 一开始竟然没看出来--甚至以为是VS中出现"宏可以转换为constexpr"问题--下次要仔细--
- 再谈vbo
我们之前都是通过glNamedBufferData初始化buffer object,初始化的意思是为buffer object开辟显存空间,并填充数据: GLfloat position[] = { ...
- MSSQL·查询T-SQL语句执行时间的三种方法
阅文时长 | 0.23分钟 字数统计 | 420.8字符 主要内容 | 1.引言&背景 2.自定义时间变量求差法 3.MSSQL内置方法 4.MSSQL选项开启时间统计 5.声明与参考资料 『 ...
- 利用Typora+PicGo+OSS+Git+Github/码云搭建个人云笔记
搭建个人云笔记 对于程序员来讲,使用markdown可以帮助我们快速地写作,书写出排版好看,颜值高的笔记,使用markdown来书写文档相比于使用word要简单快捷的多 市面上有很多markdown的 ...
- 【Web前端HTML5&CSS3】08-盒模型补充
笔记来源:尚硅谷Web前端HTML5&CSS3初学者零基础入门全套完整版 目录 盒模型补充及田径场实战 1. 盒子大小 2. 轮廓 3. 阴影 4. 圆角 圆 椭圆 盒模型补充及田径场实战 1 ...
- ruby基础(四)
ruby基础知识 模块 模块是ruby的特色功能之一.如果说类是事物的实体以及行为,那么模块表现的 就是事物的行为部分,模块和类有以下两点不同: 模块不能拥有实例 模块不能被继承 模块的使用方法 mo ...
- openstack创建vlan网络并配置网络设备
1.在管理员-->网络-->创建网络. 2.填写网络信息,这里要划分新的VLAN,注意在物理网络中填写的事VLAN,段ID指的是vlan的id 3.创建的网络. 4.创建子网,在里面修改子 ...
- property - 必应词典 美['prɑpərti]英['prɒpə(r)ti] n.属性;财产;财产权;【戏】道具
英语 (已检测) 自动检测 阿拉伯语 自动检测 爱尔兰语 自动检测 爱沙尼亚语 自动检测 保加利亚语 自动检测 冰岛语 自动检测 波兰语 自动检测 波斯尼亚语(拉丁语) 自动检测 波斯语 自动检测 丹 ...
- libvirtd 启动成功,但却没有监听
现象: 执行 systemctl start libvirtd在其它机器上进行测试是否监听:virsh -c qemu+tcp://host/system libvirtd启动成功,没有报错,但却没有 ...