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

作者 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");
        }

    }
}

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

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

阿里代码规范 :
【强制】异常不要用来做流程控制,条件控制。
说明:异常设计的初衷是解决程序运行中的各种意外情况,且异常的处理效率比条件判断方式要低很多。
更重要的是,代码可读性太差了,随时一个方法的异常抛出来,还要考虑代码本身的异常。

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

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

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

我们希望达到的目的

代码没有这么多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注解的大小,越小,优先级越高
代码清晰,所有处理逻辑下沉到实现类中
使用设计模式的缺点

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

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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容

  • iOS网络架构讨论梳理整理中。。。 其实如果没有APIManager这一层是没法使用delegate的,毕竟多个单...
    yhtang阅读 5,175评论 1 23
  • 创建型模式 工厂模式 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设...
    liuyang7519阅读 324评论 0 2
  • 心理学中,常常把行为与动机联系起来。而作为一门研究人的心理与行为的独立学科来讲,行为就是有机体在各种内外部刺激影响...
    锦帆w阅读 3,901评论 0 4
  • 刚从深圳来到这里,已然来到了另一片天地,什么都是新奇的,初始印象只有两个词:干净,漂亮!妞开车带我回到村里的屋子里...
    Csmessi阅读 499评论 3 3
  • 小编觉得,算不上好。同是芒果台第二梯队的主持人,在资源上一定有竞争,所以两人不会是好友、最多算同事吧。 在之前的一...
    文琪来啦阅读 571评论 0 0