前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >项目优雅的实现责任链模式

项目优雅的实现责任链模式

作者头像
用户10136162
发布2023-11-01 14:58:23
2390
发布2023-11-01 14:58:23
举报
文章被收录于专栏:Eliauk的小窝Eliauk的小窝

项目优雅的实现责任链模式

1、创建抽象业务责任链组件

代码语言:javascript
复制
/**
 * 抽象业务责任链组件
 * @author zang 
 * @date 2022/10/31 22:46
 */
public interface AbstractChainHandler<T> extends Ordered {

    /**
     * 执行责任链逻辑
     *
     * @param requestParam 责任链执行入参
     */
    void handler(T requestParam);

    /**
     * @return 责任链组件标识
     */
    String mark();
}

上边的代码,是责任链模式中最顶级的解开 handler 方法,其他组件继承这个接口,然后实现 handler 方法,当作具体的实现 mark() 方法,是每个组件的标识,用于标识当前执行的某个过滤器链 这个会在某个过滤器链的顶级接口中设置

2、创建抽象责任链上下文

代码语言:javascript
复制

/**
 * 抽象责任链上下文
 *
 * @author zang
 * @date 2022/10/31 20:01
 */
public final class AbstractChainContext<T> implements CommandLineRunner {

    private final Map<String, List<AbstractChainHandler>> abstractChainHandlerContainer = new HashMap<>();

    /**
     * 责任链组件执行
     *
     * @param mark         责任链组件标识
     * @param requestParam 请求参数
     */
    public void handler(String mark, T requestParam) {
        List<AbstractChainHandler> abstractChainHandlers = abstractChainHandlerContainer.get(mark);
        if (CollectionUtils.isEmpty(abstractChainHandlers)) {
            throw new RuntimeException(String.format("[%s] Chain of Responsibility ID is undefined.", mark));
        }
        abstractChainHandlers.forEach(each -> each.handler(requestParam));
    }

    /**
     * 在SpringBoot启动时,将所有的责任链组件排好顺序注册到容器中
     * 
     * @param args
     * @throws Exception
     */
    @Override
    public void run(String... args) throws Exception {
        Map<String, AbstractChainHandler> chainFilterMap = ApplicationContextHolder
                .getBeansOfType(AbstractChainHandler.class);
        chainFilterMap.forEach((beanName, bean) -> {
            List<AbstractChainHandler> abstractChainHandlers = abstractChainHandlerContainer.get(bean.mark());
            if (CollectionUtils.isEmpty(abstractChainHandlers)) {
                abstractChainHandlers = new ArrayList<>();
            }
            abstractChainHandlers.add(bean);
            List<AbstractChainHandler> actualAbstractChainHandlers = abstractChainHandlers.stream()
                    .sorted(Comparator.comparing(Ordered::getOrder))
                    .collect(Collectors.toList());
            abstractChainHandlerContainer.put(bean.mark(), actualAbstractChainHandlers);
        });
    }
}

3、具体实现

1、 过滤器链中的顶级接口
代码语言:javascript
复制
/**
 * 用户注册责任链过滤器
 *
 */
public interface UserRegisterCreateChainFilter<T extends UserRegisterReqDTO> extends AbstractChainHandler<UserRegisterReqDTO> {

    @Override
    default String mark() {
        return UserChainMarkEnum.USER_REGISTER_FILTER.name();
    }
}
2、具体实现
代码语言:javascript
复制
/**
 * 用户注册参数必填检验
 *
 */
@Component
public final class UserRegisterParamNotNullChainHandler implements UserRegisterCreateChainFilter<UserRegisterReqDTO> {

    @Override
    public void handler(UserRegisterReqDTO requestParam) {
        Map<Function<UserRegisterReqDTO, Object>, UserRegisterErrorCodeEnum> fieldCheckMap = new HashMap<>();
        fieldCheckMap.put(UserRegisterReqDTO::getUsername, UserRegisterErrorCodeEnum.USER_NAME_NOTNULL);
        fieldCheckMap.put(UserRegisterReqDTO::getPassword, UserRegisterErrorCodeEnum.PASSWORD_NOTNULL);
        fieldCheckMap.put(UserRegisterReqDTO::getPhone, UserRegisterErrorCodeEnum.PHONE_NOTNULL);
        fieldCheckMap.put(UserRegisterReqDTO::getIdType, UserRegisterErrorCodeEnum.ID_TYPE_NOTNULL);
        fieldCheckMap.put(UserRegisterReqDTO::getIdCard, UserRegisterErrorCodeEnum.ID_CARD_NOTNULL);
        fieldCheckMap.put(UserRegisterReqDTO::getMail, UserRegisterErrorCodeEnum.MAIL_NOTNULL);
        fieldCheckMap.put(UserRegisterReqDTO::getRealName, UserRegisterErrorCodeEnum.REAL_NAME_NOTNULL);

        fieldCheckMap.forEach((fieldGetter, errorCode) -> {
            Object fieldValue = fieldGetter.apply(requestParam);
            if (Objects.isNull(fieldValue)) {
                throw new ClientException(errorCode);
            }
        });
    }

    /**
     * 用户返回当前的的过滤器节点在当前责任链中的优先级
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

我们在使用的时候只需要在业务层,将抽象责任链上下文注入,然后执行handler() 方法将当前责任链的具体实现命传入就可以, 例如handler(UserChainMarkEnum.USER_REGISTER_FILTER.name(), requestParam);

3、后续扩展

后续如果需要增加责任链节点只需要实现对应的责任链顶级接口就可以了 后续如果需要增加新的责任链,只需要创建一个当前责任链顶级接口,继承 AbstractChainHandler 然后去做具体业务实现就可以了

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-10-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 项目优雅的实现责任链模式
    • 1、创建抽象业务责任链组件
      • 2、创建抽象责任链上下文
        • 3、具体实现
          • 1、 过滤器链中的顶级接口
          • 2、具体实现
        • 3、后续扩展
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档