欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

【转】消除代码中的 if-else/switch-case

程序员文章站 2022-06-25 15:52:56
在很多时候,我们代码中会有很多分支,而且分支下面的代码又有一些复杂的逻辑,相信很多人都喜欢用 if-else/switch-case 去实现。做的不好的会直接把实现的代码放在 if-else/switch-case 的分支之下: 这样的代码不仅冗长,读起来也非常困难。做的好一点的会把这些逻辑封装成函 ......

在很多时候,我们代码中会有很多分支,而且分支下面的代码又有一些复杂的逻辑,相信很多人都喜欢用 if-else/switch-case 去实现。做的不好的会直接把实现的代码放在 if-else/switch-case 的分支之下:

switch ( type ) {
    case case1:
        ...
        ...
        break;
    case case2:
        ...
        ...
        break;
    case case3:
        ...
        ...
        break
    default:
        return null;
}

 这样的代码不仅冗长,读起来也非常困难。做的好一点的会把这些逻辑封装成函数然后在分支中调用:

switch ( type ) {
    case case1:
        return case1func();
    case case2:
        return case2func();
    case case3:
        return case3func();
    default:
        return null;
}

 

即使这样也是面向过程思维的写法,以前写 c 程序的时候也总喜欢这样写,毫无设计模式可言。不仅违背开闭原则,而且随着 switch-case 分支的增多,该段代码只会越来越冗长。其实这种代码已经有成熟的模式去消除诸多的 if-else/switch-case 分支。本文就教大家在 spring 中如何用注解+策略模式+简单工厂的方式消除 if-else/switch-case 。我们就拿 qq 空间的个人中心举例子,假如 qq 空间个人中心有四个 tab 分别是列出我的说说、我的日志、我的照片和我的访客。一般的后台代码很有可能如下:
//各个 tab 名称的枚举:
public enum userrelatedtype {
    /**
     * 说说
     */
    shuoshuo("说说"),

    /**
     * 日志
     */
    rizhi("日志"),

    /**
     * 发布
     */
    zhaopian("照片"),

    /**
     * 访客
     */
    fangke("");

    private string desc;

    userrelatedtype(string desc) {
        this.desc = desc;
    }

    public string getdesc() {
        return desc;
    }

    public void setdesc(string desc) {
        this.desc = desc;
    }
}

列出 qq 用户个人中心相关 tab 的代码:

public list<userrelatedvo> listrelated(userrelatedquery query){

    userrelatedtype relatedtype = userrelatedtype.valueof(stringutils.uppercase(query.gettype()) );
    switch ( relatedtype ) {
        case shuoshuo:
            return listrelatedshuoshuo( query );
        case rizhi:
            return listrelatedrizhi( query );
        case zhaopian:
            return listrelatedzhaopian( query );
        case fangke:
            return listrelatedfangke( query );
        default:
            return null;
    }
}

 而采用注解+策略模式+简单工厂,重构后代码如下:

1、定义一个注解,用来完全消除 if-else:

@target(elementtype.type)
@retention(retentionpolicy.runtime)
public @interface relatedtypeannotation {
    /**
     * 用户相关类型名称
     */
    userrelatedtype value();
}

2、先定义了个接口,所有 tab 都要实现该接口。其中 list 是 tab 数据展示的方法。

public interface userrelated {

    /**
     * 列出详细信息
     *
     * @param query
     * @return
     */
    list<userrelatedvo> list(userrelatedquery query);
}

 3、定义具体的各个 tab 的实现,继承 userrelated 策略接口

   我的说说

@component("userrelatedshuoshuo")
@relatedtypeannotation( value = userrelatedtype.shuoshuo )
public class userrelatedshuoshuo implements userrelated {
    @override
    public list<userrelatedvo> list(userrelatedquery query) {
        system.out.println("我的说说!");
        return list;
    }
}

 我的日志

@component("userrelatedrizhi")
@relatedtypeannotation( value = userrelatedtype.rizhi )
public class userrelatedrizhi implements userrelated {
    @override
    public list<userrelatedvo> list(userrelatedquery query) {
        system.out.println("我的日志!");
        return list;
    }
}

 我的照片

@component("userrelatedzhaopian")
@relatedtypeannotation( value = userrelatedtype.zhaopian )
public class userrelatedzhaopian implements userrelated {
    @override
    public list<userrelatedvo> list(userrelatedquery query) {
        system.out.println("我的照片!");
        return list;
    }
}

 我的访客

@component("userrelatedfangke")
@relatedtypeannotation( value = userrelatedtype.fangke )
public class userrelatedfangke implements userrelated {
    @override
    public list<userrelatedvo> list(userrelatedquery query) {
        system.out.println("我的访客!");
        return list;
    }
}

 3、定义一个从 spring context 获取 bean 的工具类

@component
public class springcontextutil implements applicationcontextaware {

    private applicationcontext context;

    public applicationcontext getcontext() {
        return context;
    }

    @override
    public void setapplicationcontext(applicationcontext context)throws beansexception {
        this.context = context;
    }
}

 4、定义一个简单工厂,用来生产各种 tab 对象。

 

@component
public class userrelatedfactory {

    @autowired
    springcontextutil springcontextutil;
    
    private static map<userrelatedtype, userrelated> userrelatedmap = maps.newconcurrentmap();

    //工厂将 spring 装配的相关的 bean 用 map 保存起来
    public userrelatedfactory(){
        map<string, object> beanmap = springcontextutil.getcontext().getbeanswithannotation(relatedtypeannotation.class);

        for(object userrelated : beanmap.values()) {
            relatedtypeannotation annotation = userrelated.getclass().getannotation(relatedtypeannotation.class);
            userrelatedmap.put(annotation.value(), (userrelated)userrelated);
        }
    }

    public static userrelated createrelated(userrelatedtype relatedtype) {
        return userrelatedmap.get( relatedtype );
    }
}

 5、调用的代码(listrelated 会在 controller 中被调用)。

public list<userrelatedvo> listrelated(userrelatedquery query){

    userrelatedtype relatedtype = userrelatedtype.valueof(stringutils.uppercase(query.gettype()) );
    userrelated related = userrelatedfactory.createrelated( relatedtype );
    if( related != null ) {
        return related.list( query );
    } else {
        return null;
    }
}

 

 重构后的代码如果需要再新增一种 tab,比如我的好友,只需要新增一种类型继承 userrelated 实现其中的 list,并加上相应的注解即可。

 

作者:水目沾
链接:https://juejin.im/post/5ca9f113e51d452b5e458ec3
来源:掘金