软件编程
位置:首页>> 软件编程>> java编程>> Spring如何消除代码中的if-else/switch-case

Spring如何消除代码中的if-else/switch-case

作者:水目沾  发布时间:2021-12-12 03:04:47 

标签:spring,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,并加上相应的注解即可。

其实这是一种通用的解决方案,当你 if-else/switch-case 的分支超过 3 个、且分支代码相似且冗长的情况下就应该考虑这种模式。这种模式写出的代码面向对象、清晰、易扩展还高大上,何乐而不为呀,赶紧试试吧!

来源:https://juejin.im/post/5ca9f113e51d452b5e458ec3

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com