【转】消除代码中的 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 ...
随机推荐
- python 二分查找法
@source_data:数据集 @binary_num:要查找的数 @mid:中间数的键值 def binary_search(source_data,search_num): #传入数据集计算中间 ...
- TCP/IP(八)之总结TCP/IP四层模型
阅读目录(Content) 一.TCP/IP参考模型概述 1.1.TCP/IP参考模型的层次结构 二.TCP/IP四层功能概述 2.1.主机到网络层 2.2.网络互连层 2.3.传输层 2.3.应用层 ...
- 【react】利用shouldComponentUpdate钩子函数优化react性能以及引入immutable库的必要性
凡是参阅过react官方英文文档的童鞋大体上都能知道对于一个组件来说,其state的改变(调用this.setState()方法)以及从父组件接受的props发生变化时,会导致组件重渲染,正所谓&qu ...
- 【高速接口-RapidIO】6、Xilinx RapidIO核仿真与包时序分析
提示:本文的所有图片如果不清晰,请在浏览器的新建标签中打开或保存到本地打开 一.软件平台与硬件平台 软件平台: 操作系统:Windows 8.1 64-bit 开发套件:Vivado2015.4.2 ...
- JavaScript 基础排序的实现(二)
继上一篇O(n^2)的排序算法后,这一篇主要记录O(n*logn)的排序算法 1.快排(快速排序) 这一算法的核心思想为,先随机选一个数作为标兵或者说是标记(这个数一般来说选择该无序数组的中间那个元素 ...
- 吴恩达机器学习笔记39-误差分析与类偏斜的误差度量(Error Analysis and Error Metrics for Skewed Classes)
如果你准备研究机器学习的东西,或者构造机器学习应用程序,最好的实践方法不是建立一个非常复杂的系统,拥有多么复杂的变量:而是构建一个简单的算法,这样你可以很快地实现它. 构建一个学习算法的推荐方法为:1 ...
- soul开源网关项目搭建学习
1. soul开源网关项目搭建学习 1.1. 地址 https://gitee.com/shuaiqiyu/soul 1.2. 介绍 官方介绍:这是一个异步的,高性能的,跨语言的,响应式的API网关. ...
- Redis 设计与实现 (一)--数据结构
底层数据结构:动态字符串.字典.整数集合.双端链表.压缩列表 字符串对象: int 浮点数值 raw 字符串值>32字节 embstr 字符串值<32字节 字符串编码转换: i ...
- PHP中的自动加载
自动加载? 或许你已经对自动加载有所了解.简单描述一下:自动加载就是我们在new一个class的时候,不需要手动去写require来导入这个class.php文件,程序自动帮我们加载导入进来.这是 ...
- Mysql实现null值排在最前或最后
最近在做项目迁移,Oracle版本的迁到Mysql版本,遇到有些oracle的函数,mysql并没有,所以就只好想自定义函数或者找到替换函数的方法进行改造. oracle做数据排序的时候,有时候可以用 ...