策略模式优化if-else

前言:

  当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.

posted @   杨岂  阅读(1138)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类
点击右上角即可分享
微信分享提示