策略模式+工厂模式的使用

2023-11-12

在项目开发过程中,经常会遇到项目代码中充斥着大量的if-else,每次增加类型都要整体代码逻辑看一遍才可以修改,如下代码:

if("wx".equals(type)){
    do...
}else if("zfb".equals(type)){
    do...
}else if("bank".equals(type)){
    do...
}else{
    do...
}

当业务逻辑不变时使用以上代码是没有什么问题的,但业务经常变动时,就需要经常改动代码,如果后期再增加分支,每次改动都需要对每个分支都做测试,增加测试工作量同时要不利于代码维护,也违反开闭原则和单一职责,这时候我们就要想办法来优化这样的代码.

代码改造:

下面我们使用策略模式+工厂来改造以上代码,

1. 使用idea创建一个SpirngBoot工程,创建支付类枚举,创建一个PayHandler接口类

public enum PayChannelEnum {
    ZFB("支付宝支付"),
    WX("微信支付"),
    BANK("银行卡支付");
    private String desc;
    private String beanName;
    PayChannelEnum(String desc) {
        this.desc = desc;
    }
    public String getDesc() {
        return desc;
    }
}
public interface PayHandler {
    PayChannelEnum getPayChannel();
    void pay();
}

2. 创建三个支付通道的处理类,实现PayHandler,注意加@Component

@Component
public class BankPayHandler implements PayHandler {
    @Override
    public PayChannelEnum getPayChannel() {
        return PayChannelEnum.BANK;
    }

    @Override
    public void pay() {
        System.out.println("银行卡支付");
    }
}
@Component
public class WxPayHandler implements PayHandler {
    @Override
    public PayChannelEnum getPayChannel() {
        return PayChannelEnum.WX;
    }
    @Override
    public void pay() {
        System.out.println("微信支付");
    }
}
@Component
public class ZfbPayHandler implements PayHandler {
    @Override
    public PayChannelEnum getPayChannel() {
        return PayChannelEnum.ZFB;
    }

    @Override
    public void pay() {
        System.out.println("支付宝支付");
    }
}

3. 创建工厂类,实现InitializingBean, ApplicationContextAware.

@Component
public class PayFactory implements InitializingBean, ApplicationContextAware {

    private static final Map<String,PayHandler> payHandlerMap = new ConcurrentHashMap<>();

    private ApplicationContext applicationContext;

    public PayHandler getPayHandler(String name){
        return payHandlerMap.get(name);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        applicationContext.getBeansOfType(PayHandler.class)
                .values()
                .forEach(handler -> payHandlerMap.put(handler.getPayChannel().name(),handler));

    }

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

4. 使用

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
        PayFactory payFactory = (PayFactory) context.getBean("payFactory");
        payFactory.getPayHandler(PayChannelEnum.ZFB.name()).pay();
    }

}

总结:

根据上面代码我们能看出策略模式优点缺点很明显,在项目中使用要根据自己业务的实际情况来确定.

优点: 符合单一职责和开闭原则,使代码易于扩展和复用

缺点: 每个类型都需要一个实现一个策略类,会使代码出现"膨胀",调用方要预先知道所有的类型

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

策略模式+工厂模式的使用 的相关文章

随机推荐

  • Java的jdk安装教程:

    一 jdk安装流程 1 从官网下载jdk https www oracle com java technologies downloads 2 进入官网 3 选择需要的版本 4 下载后 双击安装 二 配置环境变量 1 桌面右键计算机点击属性
  • 利用Audacity软件分析ctf音频隐写

    分析音频得到摩斯电码 看波的宽度分辨长短音 比较细的就是短音 代表 比较粗的就是长音 代表 中间的间隔就是 得到摩斯电码
  • unity点击场景内物体进行交互

    提示 本文展示点击事件 另有其他自行研究 前言 一 原理 二 使用步骤 1 使用前提 2 使用脚本 总结 前言 很多情况下我们需要对场景内的物体进行交互 今天我们采用射线检测的方法进行点击 例如 点击场景内的Cube 进行开始旋转 提示 以
  • 宏DECLARE_DYNCREATE与DECLARE_DYNAMIC

    一 作用 DECLARE DYNCREATE的主要作用 支持对象的动态创建 使用 DECLARE DYNCREATE 宏声明的类可以在运行时动态创建对象 支持对象的序列化 MFC框架提供了对象的序列化支持 允许将对象的状态保存到磁盘 序列化
  • VS2010编译QT4.8.4遇到“LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 “问题

    在用VS编译qt时候很少有人遇到如上所示问题 因此当我遇到时很不幸的找不到对应的解决办法 相关的国内外网站资料没有少折腾可都不行 还有的说修改项目属性 但这种方法只适合对具体的项目就行修改 在编译qt的时候就丈二和尚摸不着头脑 下面就介绍一
  • 分页显示该休矣

    当你有很多东西要显示给用户 而且内容多得远非一个屏幕可以放得下的时候 你会怎么办 很自然 你会想到分页 在2007年 Vitaly Friedman写了一篇文章叫 Pagination Gallery ExamplesAnd Good Pr
  • 【android】数据库升级完整解决方案

    作者 飞翔的猫咪 http flyingcat2013 blog 51cto com 7061638 1537074 原创作品 允许转载 转载时请务必以超链接形式标明文章 原始出处 作者信息和本声明 否则将追究法律责任 http flyin
  • 如何计算c++中开数组中占的内存

    如何计算c 中开数组中占的内存 引入 在比赛中一般都会有数组的身影 但是比赛时内存是一定的 若是操作不当 那么正解也会被数组而拖累 可是如何确保自己的数组占的内存的呢 首先要知道你自己开数组是的类型是不一样的内存的 也就是说类型不一样 内存
  • Android Studio操作SQLite数据库简要示例

    Android Studio操作SQLite数据库 主要分三步 1 创建数据库及数据表 2 写数据库表 3 读数据库表 下面用例子进行介绍 我们做一个简单的登记用户名及电话号码并进行显示的例子 首先创建EmptyActivity工程Test
  • [深入研究4G/5G/6G专题-34]: URLLC-5-《中国联通5G URLLC技术白皮书3.0版本》解读-1-业务场景

    目录 第1章 背景与URLLC的发展历程 1 1 URLLC的应用场景 1 2 URLLC的业务特点 第2章 URLLC的业务需求
  • 南京邮电大学操作系统复试

    目录 第 1 章 计算机系统概述 多道运行的特征 第 2 章 进程与线程 2 1 进程与线程 1 进程与程序 2 PID Process ID 进程ID 3 PCB Process Control Block 进程控制快 4 进程的特征 5
  • 【NAS工具箱】Pytorch中的Buffer

    Parameter 模型中的一种可以被反向传播更新的参数 第一种 直接通过成员变量nn Parameter 进行创建 会自动注册到parameter中 def init self super MyModel self init self p
  • 垃圾收集器知识点4:Java中垃圾收集器的实现

    目录 java8垃圾收集器组合一览 serial GC 串行GC 的实现 串行gc日志分析 Minor GC 小型GC Full GC 完全GC Parallel GC 并行GC 的实现 并行GC日志分析 Minor GC 小型GC Ful
  • 第二十九章、containers容器类部件QFrame框架部件详解

    一 概述 容器部件就是可以在部件内放置其他部件的部件 在Qt Designer中可以使用的容器部件有如下 容器中的Frame为一个矩形的框架对象 对应类QFrame QFrame类是PyQt中带框架部件的所有类的基类 如菜单 进度条 Lab
  • SQLServer 数据加密解密:常用的加密解密(一)

    都是基本示例 更多参考官方文档 1 Transact SQL 函数 2 数据库密钥 3 证书 4 非对称密钥 5 对称密钥 sql view plain copy drop table EnryptTest create table Enr
  • Win10 WSL运行docker报错:Cannot connect to the Docker daemon at unix:///var/run/docker.sock.

    我安装的子系统是Ubuntu 1804 安装docker步骤如下 sudo apt update 更新软件源 sudo apt install y docker io 安装docker sudo usermod aG docker leo
  • 3个技术男搞恋爱版ChatGPT,估值10亿美元

    过去几个月 我们见证了GPT从3 5到4 0 从只能做结构化搜索整合到接近人类思维的对话 我们还看到了 GPT逐步掌握画画 写作 剪辑 制表 做 PPT 等技能 最可怕的是AI的迭代速度 简直是一天一个样 这股这股前所未有的技术浪潮 一时间
  • sklearn中的LogisticRegression

    sklearn中的逻辑回归接口如下 sklearn linear model LogisticRegression penalty l2 dual False tol 0 0001 C 1 0 fit intercept True inte
  • [专利与论文-14]:研究员级(正高)高级工程师评审不通过的常见原因(实际案例)

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 专利与论文 14 研究员级 正高 高级工程师评审不通过的常见原因 实际案例 文火冰糖 王文兵 的博客 CSDN博客 作者主页 文火冰糖的硅基
  • 策略模式+工厂模式的使用

    在项目开发过程中 经常会遇到项目代码中充斥着大量的if else 每次增加类型都要整体代码逻辑看一遍才可以修改 如下代码 if wx equals type do else if zfb equals type do else if ban