前言:

  当if else的条件少的话,代码可阅读性及逻辑不影响阅读和扩展。一旦if else过多的话会导致逻辑比较混乱,不易扩展并且很容易出错。

实现方案:

  1、定义一个@HandlerType注解,一个value属性,其值对应 if 条件的值

  2、定义一个接口或者抽象类,抽AbstractHandler,抽象逻辑处理方法handler方法交给具体的业务实现

  3、根据自己的业务,定义多个类实现AbstractHandler接口。每个实现类都注册到Spring容器中

  4、对每个AbstractHandler的实现类都标注上@HandlerType注解,值为其要处理 if 条件的值

  5、定义一个HandlerContext,用来扫描具有 @HandlerType注解的类,并将注解中的value作为key,对应的类作为value,初始化其属性handlerMap

  6、通过条件从Spring容器中获取一个对应的AbstractHandler实例

  7、执行实例对应的handler方法

举个例子:

  有这样一个需求,需要监听一个Kafka topic下的不同类型的消息,类型从监听到的message中去区分,不同的类型的消息,处理逻辑也不同。代码:

  1、定义自定义注解

/**
* Kafka监听消息的topic动作编号
*
* @author yangyongjie
* @date 2019/11/7
* @desc
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ListenerAction {
/**
* topic动作编号
*
* @return
*/
int value();
}

  2、定义抽象处理器

/**
* 抽象的Kafka消息处理器
*
* @author yangyongjie
* @date 2019/11/7
* @desc
*/
public abstract class AbstractListenerHandler {
/**
* 消息处理
*
* @param data
*/
public abstract void handler(String data);
}

  

  3、具体实现处理器,多个,这里只列一个

  4、在具体的处理器上标注@HandlerType注解,表示其要处理的逻辑分支,这里表示只处理action为2001的消息

/**
* PartnerId 变更消息监听处理器
* @author yangyongjie
* @date 2019/11/7
* @desc
*/
@ListenerAction(2001)
@Component
public class PartnerIdListenerHandler extends AbstractListenerHandler { @Override
public void handler(String data) {
// dosomething
}
}

  

  5、扫描具有 @HandlerType注解的类,并将注解中的value作为key,对应的类作为value,初始化其属性handlerMap

**
* 消息处理器的处理器
* 1.扫描包中标有@ListenerAction注解的类
* 2.将注解中的动作编号值作为key,对应的类作为value,初始化handlerMap
*
* @author yangyongjie
* @date 2019/11/7
* @desc
*/
@Component
public class ListenerHandlerContext implements ApplicationContextAware { private ApplicationContext applicationContext; /**
* 保存处理器的map,key为action,value为处理器Class
*/
private static final Map<Integer, Class> HANDLER_MAP = new HashMap<>(4); public AbstractListenerHandler getListenerHandlerInstance(Integer action) throws BssException {
Class<?> clazz = HANDLER_MAP.get(action);
if (clazz == null) {
throw new BssException(ResponseEnum.ERROR_HANDLER_NOT_FOUND.getCode(), ResponseEnum.ERROR_HANDLER_NOT_FOUND.getMsg());
}
return (AbstractListenerHandler) applicationContext.getBean(clazz);
} /**
* 扫描@ListenerAction,初始化ListenerHandlerContext,将其注册到Spring容器中
*
* @param applicationContext
* @throws BeansException
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
// 遍历所有带有@ListenerAction注解的类
Map<String, Object> listenerHandlerBeans = applicationContext.getBeansWithAnnotation(ListenerAction.class);
if (MapUtils.isNotEmpty(listenerHandlerBeans)) {
for (Object listenerHandlerBean : listenerHandlerBeans.values()) {
Integer action = listenerHandlerBean.getClass().getAnnotation(ListenerAction.class).value();
HANDLER_MAP.put(action, listenerHandlerBean.getClass());
}
}
}
}

  6、获取处理器,执行逻辑分支

@Autowired
private ListenerHandlerContext listenerHandlerContext;
...
// 获取消息监听处理器
AbstractListenerHandler listenerHandler = listenerHandlerContext.getListenerHandlerInstance(action);
// kafka消息逻辑处理
listenerHandler.handler(data); 

  END.

策略模式优化过多的IF ELSE的更多相关文章

  1. 用工厂模式和策略模式优化过多的if-else

    多个if-else代码: @RunWith(SpringRunner.class) @SpringBootTest public class EducationalBackgroundTest { p ...

  2. 代码重构:用工厂+策略模式优化过多的if else代码块

    最近在工作中优化了一段冗余的if else代码块,感觉对设计模式的理解和运用很有帮助,所以分享出来.鉴于原代码会涉及到公司的隐私,因此就不贴出来了.下面以更加通俗易懂的案例来解析. 假如写一个针对员工 ...

  3. 利用策略模式优化过多 if else 代码

    前言 不出意外,这应该是年前最后一次分享,本次来一点实际开发中会用到的小技巧. 比如平时大家是否都会写类似这样的代码: if(a){ //dosomething }else if(b){ //dosh ...

  4. 代码重构:用工厂+策略模式优化冗余的if else代码块

    最近在工作中优化了一段冗余的if else代码块,感觉对设计模式的理解和运用很有帮助,所以分享出来.鉴于原代码会涉及到公司的隐私,因此就不贴出来了.下面以更加通俗易懂的案例来解析. 假如写一个针对员工 ...

  5. Java策略模式以及来自lambda的优化

    前言    设计模式是软件工程中一些问题的统一解决方案的模型,它的出现是为了解决一些普遍存在的,却不能被语言特性直接解决的问题,随着软件工程的发展,设计模式也会不断的进行更新,本文介绍的是经典设计模式 ...

  6. 新来的"大神"用策略模式把if else给"优化"了,技术总监说:能不能想好了再改?

    本文来自作者投稿,原作者:上帝爱吃苹果 目前在魔都,贝壳找房是我的雇主,平时关注一些 java 领域相关的技术,希望你们能在这篇文章中找到些有用的东西.个人水平有限,如果文章有错误还请指出,在留言区一 ...

  7. Java设计模式从精通到入门三 策略模式

    介绍 我尽量用最少的语言解释总结: Java23种设计模式之一,属于行为型模式.一个类的行为或者算法可以在运行时更改,策略对象改变context对象执行算法. 应用实例: ​ 以周瑜赔了夫人又折兵的例 ...

  8. JAVA设计模式之策略模式 - Strategy

    在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改.这种类型的设计模式属于行为型模式. 在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 ...

  9. java使用策略模式代替if/else

    平时在开发中避免不了使用大量的if else语句,但过多层的if else对于性能有很大的开销,类似如下代码 public class MainStart { public static void m ...

随机推荐

  1. liunx 定时任务crontab格式说明

    每分钟执行 */1 * * * * 每小时执行 0 * * * * 每天执行 0 0 * * * 每周执行 0 0 * * 0 每月执行 0 0 1 * * 每年执行 0 0 1 1 *

  2. python进行数据库迁移的时候显示(TypeError: __init__() missing 1 required positional argument: 'on_delete')

    进行数据库迁移的时候,显示  TypeError: __init__() missing 1 required positional argument: 'on_delete' 图示: 出现原因: 在 ...

  3. Zuul网关过滤器中转发头信息不起作用

    大家应该都知道在做Zuul网关过滤的时候,如果不在网关过滤时转发头信息,经过网关时头信息就会丢失. 但我用 addZuulRequestHeader转发头信息时,却不起作用,在子服务的controll ...

  4. gradle使用方法

    创建一个项目 你可以通过创建一个build.gradle的文件来开始一个项目,然后可以向文件中加入构建逻辑. $ mkdir basic-demo $ cd basic-demo $ touch bu ...

  5. c语言秋季作业2

    问题 答案 这个作业属于哪个课程 C语言程序设计I 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-4/homework/8657 我在这 ...

  6. (4.14)mysql备份还原——mysql物理热备工具之ibbackup

    关键词:mysql热备工具,ibbackup,mysql物理备份工具 1. 准备 ibbackup 是 InnoDB 提供的收费工具,它支持在线热备 InnoDB 数据,主要有以下特性: * Onli ...

  7. SQL基本语法和书写格式

    插入 insert [into] 表名 [(列名列表)] values (值列表) insert into 新表名 (列名列表) select 列名列表 from 表名 select 表名.列名 in ...

  8. selenium安装及环境搭建

    说明:安装selenium前提必须是安装好了python和pip 1.安装python 在Python的官网 www.python.org 中找到最新版本的Python安装包(我的电脑是windows ...

  9. python 二维数组转一维数组

    三种方法 比如 a = [[1, 2], [3, 4], [5, 6]] 列表推导式 [i for j in a for i in j] 库函数 from itertools import chain ...

  10. java 线程池(线程的复用)

    一. 线程池简介 1. 线程池的概念: 线程池就是首先创建一些线程,它们的集合称为线程池.使用线程池可以很好地提高性能,线程池在系统启动时即创建大量空闲的线程,程序将一个任务传给线程池,线程池就会启动 ...