【日常业务开发】策略+工厂模式优化 if...else判断逻辑

news2024/11/17 17:53:14

【日常业务开发】策略+工厂模式优化 if...else判断逻辑

  • 场景
  • 策略+工厂模式优化
    • 利用Spring自动注入的特点处理
    • 继承InitializingBean+静态工厂方法调用处理
    • 注解+CommandLineRunner+ApplicationContextAware处理/ApplicationListener\<ContextRefreshedEvent>

场景

业务中经常有支付业务,项目刚开始所有业务使用支付宝支付,后面湖南地区需要使用微信支付,然后湖北又需要使用易宝支付,后期可能还有扩展。如果使用if…else逻辑,业务中经常要写的代码:

public static void pay() {
    // String fruit = "aliPay";
    // String fruit = "yiBaoPay";
    String payType = "weiXinPay";
    if ("aliPay".equals(payType)){
        log.info("===调用支付宝接口发起支付业务===");
    } else if ("yiBaoPay".equals(payType)){
        log.info("===调用易宝接口发起支付业务===");
    } else {
        log.info("===调用微信接口发起支付业务===");
    }
}

如何优雅的处理消除if…else逻辑,方面后期扩展呢?策略+工厂模式优化

策略+工厂模式优化

在这里插入图片描述

利用Spring自动注入的特点处理

支付接口IPay和具体实现类AliPay、WeiXinPay、YiBaoPay

public interface IPay {
    String pay();
}

@Service
@Slf4j
public class AliPay implements IPay {

    @Override
    public String pay() {
        log.info("===调用支付宝接口发起支付业务===");
        return "调用支付宝接口发起支付业务";
    }
}

@Service
@Slf4j
public class WeiXinPay implements IPay {
    @Override
    public String pay() {
        log.info("===调用微信接口发起支付业务===");
        return "调用微信接口发起支付业务";
    }
}

@Service
@Slf4j
public class YiBaoPay implements IPay {
    @Override
    public String pay() {
        log.info("===调用易宝接口发起支付业务===");
        return "调用易宝接口发起支付业务";
    }
}

工厂类PayFactory

@Component
public class PayFactory {
    /**
     * 利用Spring自动注入的特点。Key为bean的名称、value为IPay接口对应的bean实现类
     */
    @Autowired
    Map<String, IPay> map;

    public  IPay getInstance(String type) {
        return map.get(type);
    }
}
@RestController
public class PayController {

    @Autowired
    private PayFactory payFactory;

    @GetMapping("/alipay")
    public String aliPay(String type) {
        IPay pay = payFactory.getInstance(type);
        return pay.pay();
    }
}

Key为bean的名称、value为IPay接口对应的bean实现类。对应的业务类型不好扩展

继承InitializingBean+静态工厂方法调用处理

public interface IPay extends InitializingBean {
    String pay();
}


@Service
@Slf4j
public class AliPay implements IPay {

    @Override
    public String pay() {
        log.info("===调用支付宝接口发起支付业务===");
        return "调用支付宝接口发起支付业务";
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        PayFactory.registerHandler("ali", this);
    }
}

@Service
@Slf4j
public class WeiXinPay implements IPay {
    @Override
    public String pay() {
        log.info("===调用微信接口发起支付业务===");
        return "调用微信接口发起支付业务";
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        PayFactory.registerHandler("weixin", this);
    }
}

@Service
@Slf4j
public class YiBaoPay implements IPay {
    @Override
    public String pay() {
        log.info("===调用易宝接口发起支付业务===");
        return "调用易宝接口发起支付业务";
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        PayFactory.registerHandler("yibao", this);
    }
}

工厂类PayFactory,暴露注册bean到工厂容器Map对象方法,提供根据type类型查询bean的静态方法

public class PayFactory {
    private static final Map<String, IPay> PAY_MAP = new HashMap<>();
    /**
     * 获取对应实例Bean
     * @param type
     * @return
     */
    public static IPay getInstance(String type) {
        return PAY_MAP.get(type);
    }

    /**
     * 注册bean到工厂容器对象
     * @param handlerName
     * @param pay
     */
    public static void registerHandler(String handlerName, IPay pay) {
        PAY_MAP.put(handlerName, pay);
    }
}

注解+CommandLineRunner+ApplicationContextAware处理/ApplicationListener<ContextRefreshedEvent>

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface PayCode {
    String value();
    String name();
}

public interface IPay {
    String pay();
}

@PayCode(value = "alia", name = "支付宝支付")
@Service
@Slf4j
public class AliPay implements IPay {

    @Override
    public String pay() {
        log.info("===调用支付宝接口发起支付业务===");
        return "调用支付宝接口发起支付业务";
    }
}

@PayCode(value = "weixin", name = "微信支付")
@Service
@Slf4j
public class WeiXinPay implements IPay {
    @Override
    public String pay() {
        log.info("===调用微信接口发起支付业务===");
        return "调用微信接口发起支付业务";
    }
}

@PayCode(value = "yibao", name = "易宝支付")
@Service
@Slf4j
public class YiBaoPay implements IPay {
    @Override
    public String pay() {
        log.info("===调用易宝接口发起支付业务===");
        return "调用易宝接口发起支付业务";
    }
}

第一种方式: 工厂类PayFactory实现Spring生命周期函数在run方法中处理被标记的@PayCode的bean对象加入到静态容器Map中:

  • CommandLineRunner:当前Bean被IOC容器装配完成调用run()方法

  • ApplicationContextAware: 获取容器对象ApplicationContext

@Component
public class PayFactory implements CommandLineRunner, ApplicationContextAware {

    private ApplicationContext applicationContext;

    private static final Map<String, IPay> PAY_MAP = new HashMap<>();

    /**
     * 获取对应实例Bean
     * @param type
     * @return
     */
    public static IPay getInstance(String type) {
        return PAY_MAP.get(type);
    }


    @Override
    public void run(String... args) throws Exception {
        Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(PayCode.class);
        if (beansWithAnnotation !=null ) {
            beansWithAnnotation.forEach((k,v)->{
                PayCode payCodeAnn = v.getClass().getAnnotation(PayCode.class);
                PAY_MAP.put(payCodeAnn.value(), (IPay)v);
            });
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

第二种方式: 实现ApplicationListener<ContextRefreshedEvent>监听事件接口代替CommandLineRunner, ApplicationContextAware

ContextRefreshedEvent事件: ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在ConfigurableApplicationContext接口中使用 refresh()方法来发生。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用。

@Component
public class PayFactory implements ApplicationListener<ContextRefreshedEvent> {

    private static final Map<String, IPay> PAY_MAP = new HashMap<>();

    /**
     * 获取对应实例Bean
     * @param type
     * @return
     */
    public static IPay getInstance(String type) {
        return PAY_MAP.get(type);
    }
    
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        ApplicationContext applicationContext = event.getApplicationContext();
        Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(PayCode.class);
        if (beansWithAnnotation !=null ) {
            beansWithAnnotation.forEach((k,v)->{
                PayCode payCodeAnn = v.getClass().getAnnotation(PayCode.class);
                PAY_MAP.put(payCodeAnn.value(), (IPay)v);
            });
        }
    }
}
@RestController
public class PayController {
    
    @GetMapping("/alipay")
    public String aliPay(String type) {
        IPay pay = PayFactory.getInstance(type);
        return pay.pay();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/160321.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一行代码写一个谷歌插件 —— Javascript

回顾 前期 【提高代码可读性】—— 手握多个代码优化技巧、细数哪些惊艳一时的策略_0.活在风浪里的博客-CSDN博客代码优化对象策略https://blog.csdn.net/m0_57904695/article/details/128318224?spm1001.2014.3001.5501 目录 技巧一&#xff1a;谷歌插件 第一步: 第二步…

Tomcat的安装和使用

作者&#xff1a;~小明学编程 文章专栏&#xff1a;JavaEE 格言&#xff1a;热爱编程的&#xff0c;终将被编程所厚爱。 目录 下载Tomcat tomcat文件介绍 启动Tomcat 简单的部署静态页面 HTTP 服务器&#xff0c;就是在 TCP 服务器的基础上&#xff0c;加上了一些额外的功能…

计算机网络 - 概述

文章目录前言一、计算机网络概述1.1、计算机网络在信息时代的作用1.2、Intnet概述网络、互连网&#xff08;互联网&#xff09;和因特网因特网发展阶段因特网的组成1.3、计算机网络的定义和分类定义分类1.4、报文交换方式电路交换分组交换报文交换三种交换方式对比1.5、性能指标…

5-1输入/输出管理-I/O管理概述

文章目录一.I/O设备二.I/O控制器/设备控制器三.I/O控制方式1.程序直接控制方式2.中断驱动方式3.DMA方式&#xff08;直接存储器存取&#xff09;4.通道控制方式四.I/O子系统的层次结构五.输入/输出应用程序接口&设备驱动程序接口&#xff08;一&#xff09;输入/输出应用程…

【学Vue就跟玩一样】组件-单文件组件

单文件组件在实际开发中是经常使用的&#xff0c;那么如何创建一个单文件组件呢&#xff1f;那么本篇就来简单入一下单文件组件。一&#xff0c;创建单文件组件 1.切换到你想要创建该文件的目录下&#xff0c;我这里切换的是desktop这个目录&#xff0c;当然&#xff0c;也可以…

大学高校供配电系统谐波危害及治理方案

摘要&#xff1a;安全科学用电是保障高校教学科研及办公的基础条件&#xff0c;随着现代化教学、电子图书馆等先进教学手段的不断引入&#xff0c;智能给排水、变频空调、电梯传送系统等配套设施以及电子镇流的照明灯具设备等大量非线性电力电子设备涌现&#xff0c;很多高等院…

「科普」带你认识5G基站

随着5G时代的到来&#xff0c;为了信号的稳定传输&#xff0c;为了覆盖面更广&#xff0c;5G基站作为5G规模组网的“先行军”&#xff0c;其建设至关重要。 那么&#xff0c;5G时代的基站是如何建设的呢&#xff1f;下面就来给大家介绍一下。 截至2022年末&#xff0c;我国移…

【Lilishop商城】No4-7.业务逻辑的代码开发,涉及到:商品模块

仅涉及后端&#xff0c;全部目录看顶部专栏&#xff0c;代码、文档、接口路径在&#xff1a; 【Lilishop商城】记录一下B2B2C商城系统学习笔记~_清晨敲代码的博客-CSDN博客 全篇会结合业务介绍重点设计逻辑&#xff0c;其中重点包括接口类、业务类&#xff0c;具体的结合源代…

当代年轻人超半数人为“单身贵族”,数据可视化教你如何应付春节相亲

春节临近&#xff0c;不知大家在完成“年度总结”的同时&#xff0c;是否完成找到对象这个任务&#xff0c;如果还是单身&#xff0c;建议大家准备好如何应对家里安排的相亲吧&#xff01;现如今男女比例严重失调&#xff0c;也相对产生多数的“单身贵族”&#xff0c;当代年轻…

牛客竞赛每日俩题 - Day14

目录 错排算法 三维数组的应用 错排算法 发邮件__牛客网 错排: 假设有n封信要装入到n个信封中&#xff0c;每封信应该要放到对应的信封中&#xff0c;比如: 信: A B C D... 信封: a b c d. ... 由于疏忽将信放置出错&#xff0c;总共有多少种可能性每封信都放错 假设:D(n)…

自定义类型详解

这次我们来看自定义类型&#xff0c;我们之前接触过的自定义类型就有数组和结构体&#xff0c;我们来详细解析一下这些自定义类型的特点&#xff0c;已经一些我们没接触过的自定义类型 目录 1.结构体 1.1结构体的基础知识 1.2结构体的声明 1.3特殊声明 1.4结构的自引用 …

Mac AndroidStudio生成签名文件,显示SHA1和MD5值

一、首先&#xff0c;生成签名文件 1.点击菜单栏中的Build的。 2.弹出窗体&#xff0c;创建新的KeyStore&#xff1a;如下图。 3.生成jks文件 4.填写keystore和key密码。ketystore密码和key密码在后面会用到。其他信息也不是很重要&#xff0c;自己差不多能记住就好。 5.然后点…

设计模式学习(五):State状态模式

一、什么是State模式 在面向对象编程中&#xff0c;是用类表示对象的。也就是说&#xff0c;程序的设计者需要考虑用类来表示什么东西。类对应的东西可能存在于真实世界中&#xff0c;也可能不存在于真实世界中。 在State模式中&#xff0c;我们用类来表示状态。在现实世界中&a…

【部署】Apache DolphinScheduler 伪集群部署

【部署】Apache DolphinScheduler&#xff08;海豚&#xff09; 伪集群部署&#xff08;Pseudo-Cluster&#xff09;Standalone极速体验版DolphinScheduler 伪集群部署前置准备工作本地部署环境准备 DolphinScheduler 启动环境配置用户免密及权限配置机器SSH免密登陆启动zookee…

解决bootstrap table footerFormatter表脚和表体列错位问题

需求&#xff1a;需要把表格的一列的内容在表最下面一行进行汇总&#xff0c;显示合计 实现合计步骤&#xff1a; 1.在初始化表格时&#xff0c;开启显示表脚的属性&#xff0c;如图 2.在需要合计的列中添加footerFormatter函数&#xff0c;如图 这样就会在表格最下面显示合计…

年度征文 | 再见2022,你好2023

年度征文 | 再见2022&#xff0c;你好2023题记个人简介初衷写作展望题记 这两天打开CSDN&#xff0c;发现消息栏一直提示我写这个年度征文&#xff0c;本来觉得自己没有经验可以分享&#xff0c;毕竟自己仍处于该领域的起步阶段&#xff0c;无法给大家提供有用的建议或实用的总…

功率放大器模块是什么意思(功率放大模块工作原理)

在日常电子实验测试中&#xff0c;很多电子工程师都会经常使用到功率放大器&#xff0c;随着人们对于功率放大器的频繁使用&#xff0c;对于功放的要求也越来越多&#xff0c;有些工程师就想要使用尺寸较小的仪器&#xff0c;功率放大模块便应运而生&#xff0c;今天就请安泰电…

关于几个坐标系的关系NED ENU ROS

几个坐标系转来转去&#xff0c;时间一长又搞混了。 地球固连坐标系 WND 地球固连坐标系 NED 机体坐标系 NED 惯性系 x轴在多旋翼对称平面内指向机头&#xff08;机头方向与多旋字形或X字形相关&#xff09;。 z轴在飞机对称平面内&#xff0c;垂直轴向下。然后&#xff0c;按…

从GPT到chatGPT(二):GPT2

GPT2 文章目录GPT2前言正文摘要方法概述训练数据输入表示模型结构实验语言模型Children’s Book Test&#xff08;CBT&#xff09;LAMBADAWinograd Schema Challenge&#xff08;WSC&#xff09;Reading ComprehensionSummarizationTranslationQuestion AnsweringGeneralizatio…

Linux下搭建Git服务器

目录 步骤一.安装Git&#xff1a; 步骤二.安装Gitosis 安装Gitosis依赖的工具 进入到Gitosis目录执行&#xff1a; 出现下面的信息表示安装成功 步骤三.服务器端创建git用户来管理Git服务 服务器端的Git配置公钥 步骤四.服务器端创建Git仓库 步骤五.客户端clone服务器…