【转】消除代码中的 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;
}
//各个 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
来源:掘金
【转】消除代码中的 if-else/switch-case的更多相关文章
- Java-Annotation的一种用法(消除代码中冗余的if/else或switch语句)
Java-Annotation的一种用法(消除代码中冗余的if/else或switch语句) 1.冗余的if/else或switch 有没有朋友写过以下的代码结构,大量的if/esle判断,来选择 ...
- 使用Java8中的Optional类来消除代码中的null检查
简介 Optional类是Java 8新增的一个类,Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException). —— 每个 Java 程序员都非常了解的异常 ...
- java中的分支结构 switch case的使用
switch(A),括号中A的取值只能是整型或者可以转换为整型的数值类型,比如byte.short.int.char.string(jdk1.7后加入)还有枚举:需要强调的是:long是不能用在swi ...
- Dreamweaver中清除php代码中多余空行的方法
使用DW自带的搜索功能,利用正则表达式 使用正则表达式搜索:\r\n\s*\r\n即可搜到代码中的空行,再用回车符\n替换即可消除代码中的多余空行
- 为什么说在使用多条件判断时switch case语句比if语句效率高?
在学习JavaScript中的if控制语句和switch控制语句的时候,提到了使用多条件判断时switch case语句比if语句效率高,但是身为小白的我并没有在代码中看出有什么不同.去度娘找了半个小 ...
- C# 利用键值对取代Switch...Case语句
swich....case 条件分支多了之后,会严重的破坏程序的美观性. 比如这个 上述代码是用于两个进程之间通信的代码,由于通信的枚举特别的多,所以case的分支特别的多.导致了代码的可读性,可维护 ...
- 知识扩展--if...else...与switch...case...的执行原理
一.简述 编程语言中的条件分支结构有两种:if-else和switch-case,这两种条件分支之间可以相互转换,但是也存在一些区别,那么什么时候该用if-else,什么时候该用switch-case ...
- switch case 与 if
case 在编程中偶尔使用到switch case语句,对于case语句的处理,出现了两种错误,现总结如下: case后必须是常量.布尔类型.字符(不能是字符串): case后如果是‘||’或者‘&a ...
- Java代码消除switch/case,if/else语句的几种实现方式
转自:https://my.oschina.net/stefanzhlg/blog/372413 我们在平时的编码中,我们经常会遇到这样的情况: 使用过多的switch/case 或者 if else ...
随机推荐
- Java虚拟机:内存分配策略
版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! Java中提倡的自动内存管理机制最终可以归结为自动化的解决两个问题:给对象分配内存和回收分配给对象的内存.在之前的博客中已经详细讲解了内存 ...
- Warning: imagettfbbox(): Could not read font in XXX on line X
今天在做图形验证码的时候,在windows运行好好的代码在CentOS下却无法运行了.报了如下警告 Warning: imagettfbbox(): Could not read font in /m ...
- JavaScript使用浏览器内置XMLHttpRequest对象执行Ajax请求
所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject).XMLHttpRequest 用于在后台与服务器交换数据.这意味着可以在不重新加载整个 ...
- Android精通之AsyncTask与ListView讲解
版权声明:未经博主允许不得转载 AsyncTask 了解AsyncTask异步,需要了解一下异步任务(多线程),什么是线程,可以这么说线程好比边吃饭边看电视,AsyncTask是为了方便后台线程中操作 ...
- ruby-super用法
ruby语法-super用法 本文主要介绍ruby中super方法的使用.super方法参数传递.method执行顺序. 下面主要通过实例来说明super方法的使用: 示例1: #!/usr/bin/ ...
- Python 22端口发邮件
#!/usr/bin/python#-*-coding:UTF-8-*- import smtplibimport timeimport os from email.mime.text import ...
- python中的进制转换
python中常用的进制转化通常有两种方法: 1.用内置函数hex(),oct(),bin(),对应的数字表示为0x,0o,0b,功能是把十进制数字转化为其他进制 >>> int( ...
- IdentityServer4源码颁发token分析及性能优化
IdentityServer4源码地址 IdentityModel源码地址 以下的流程用ResourceOwnerPassword类型获取token作为介绍 分两种获取形式说明 token请求地址为默 ...
- python高级-面向对象(11)
一.面向过程和面向对象 面向过程:根据业务逻辑从上到下写代码 面向对象:将数据与函数绑定到一起,进行封装,这样能够更快速的开发程序,减少了重复代码的重写过程 二.类和对象 1.类的概念 面向对象编程的 ...
- XSS和CSRF
说到XSS这个问题,XSS又叫跨站请求攻击,大意是说比如我发表了一篇博客,然后我在自己博客里面插入了一段恶意的js脚本代码,这段代码用于获取当前用户的cookie,并发送到我的服务器,当你们在看到这篇 ...