Spring boot 运用策略模式实现避免多次使用if的操作代码

目录
  • 前言
  • 环境配置
  • 实现目标
  • 准备策略接口和具体实现策略类
    • 支付策略接口
    • 微信支付策略类
    • 支付宝支付策略类
  • 准备支付策略上下文Context和支付策略工厂类
    • 支付策略工厂类
    • 支付策略枚举类
    • 支付策略上下文
    • pageDto类
  • 客户端代码
    • 支付控制器
  • 效果
  • 新需求
    • 添加银联的支付策略类
    • 在枚举类中添加银联的支付枚举
  • 实现效果

前言

这里就不详细去介绍策略模式是怎么样的了,想了解的可以点击下面的链接

策略模式介绍的链接:策略模式的介绍

这里列出策略模式的好处

场景:某网页有个支付,其中包含了微信、支付宝等方式的支付方式 ,后续明确还会进行兼容其他的支付方式

用策略模式的好处:

  • 避免多次使用if判断具体是用哪种支付策略进行操作。
  • 因为每种策略(微信支付、支付宝支付)的内容都比较复杂。策略模式能将每种策略分离出来,方面后续维护管理

下面我们将使用Spring boot 运用策略模式,实现上面的需求

环境配置

  • JDK8
  • Spring boot 2.3.7.RELEASE
  • 整合了spring-boot-starter-web

实现目标

使用策略模式后,新加一种支付策略时,只需要在策略枚举中添加新加的策略信息,外加一个策略类即可,而不再需要添加新的if判断。

准备策略接口和具体实现策略类

支付策略接口

/**
 * 支付策略
 */
public interface PayStrategy {

    /**
     * 支付(参数就没具体写了,可以定义成每个支付必须要有的参数)
     * @return
     */
     boolean pay();
}

微信支付策略类

/**
 * 第三方——微信支付(这里注意我修改了Bean的默认命名)
 */
@Component("wechatPayStrategy")
public class WeChatPayStrategyImpl implements PayStrategy{

    /**
     * 支付
     * @return
     */
    @Override
    public boolean pay() {

        //进行微信的支付逻辑
        System.out.println("正在进行微信的支付逻辑");

        return true;
    }
}

支付宝支付策略类

/**
 * 支付宝第三方支付(这里注意我修改了Bean的默认命名)
 */
@Component("alipayStrategy")
public class AliPayStrategyImpl implements PayStrategy {

    /**
     * 支付宝支付
     * @return
     */
    @Override
    public boolean pay() {

        //进行支付宝支付逻辑
        System.out.println("进行支付宝支付逻辑");
        return true;
    }
}

上述已将各自的策略的处理类进行了分离,接下来时使用支付策略工厂类和支付策略上下文将各自的策略类联系起来

准备支付策略上下文Context和支付策略工厂类

支付策略工厂类

package com.example.springboot_strategy.strategy.factory;

import com.example.springboot_strategy.enums.PayStrategyEnum;
import com.example.springboot_strategy.strategy.PayStrategy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.swing.plaf.synth.SynthTextAreaUI;
import java.util.Map;

/**
 * 支付策略工厂类
 */
@Component
public class PayStrategyFactory {

    /**
     * 通过Spring容器的方式注入
     */
    @Resource
    private Map<String, PayStrategy> payStrategyMap;

    /**
     * 获取对应支付策略类
     * @param payStrategyEnum 支付策略枚举
     */
    public PayStrategy getPayStrategy(PayStrategyEnum payStrategyEnum){

        if(!payStrategyMap.containsKey(payStrategyEnum.getClassName())){
            System.out.println("没有对应的支付策略,无法进行支付");
            return null;
        }

        return payStrategyMap.get(payStrategyEnum.getClassName());
    }
}

这里工厂类的逻辑是利用了Spring容器的处理方式,如果有多种类同时实现了某个接口,那么可以使用Map集合接收,Map对应的泛型,String是Bean名称,PayStrategy是每个具体实现类,这样我们就可以使用Bean类型去指定具体的策略类了,然后建立一个支付策略枚举去管理这些Bean名称。同时,也可以将Bean名称与客户端定义的类型进行关联。

支付策略枚举类

/**
 * 支付策略类型
 */
public enum PayStrategyEnum {
    WECHAT_PAY("wechat","wechatPayStrategy","微信支付"),
    ALIPAY("alipay","alipayStrategy","支付宝支付")
    ;

    /**
     * 支付策略code
     */
    private String code;

    /**
     * bean名称
     */
    private String className;

    /**
     * 信息
     */
    private String info;

    PayStrategyEnum(String code,String className,String info){
        this.code=code;
        this.className=className;
        this.info=info;
    }

    public String getCode() {
        return code;
    }

    public String getClassName() {
        return className;
    }

    public String getInfo() {
        return info;
    }
}

上面枚举类中code代表的是客户端定义的类型(例如我从前端接收到的支付type,这个type可以是这个code),className顾名思义,指的是每种策略的bean名称,info是代表每种策略的内容

支付策略上下文

/**
 * 支付策略上下文
 */
@Component
public class PayStrategyContext {

    @Autowired
    private PayStrategyFactory payStrategyFactory;

    /**
     * 支付执行
     * @param payDTO 支付参数
     * @return
     */
    public boolean payHandle(PayDTO payDTO){

        //将某属性的值转换成具体的枚举。这里是根据payDTO的type字段对应枚举的code进行转换
        Optional<PayStrategyEnum> payStrategyEnumOptional = Arrays.stream(PayStrategyEnum.class.getEnumConstants())
                .filter((e) -> e.getCode().equals(payDTO.getType())).findAny();

        if(!payStrategyEnumOptional.isPresent()){
            System.out.println("匹配不到具体支付策略");
            return false;
        }
        PayStrategyEnum payStrategyEnum = payStrategyEnumOptional.get();

        PayStrategy payStrategy = payStrategyFactory.getPayStrategy(payStrategyEnum);

        //进行payDto参数的处理.....

        boolean pay = payStrategy.pay();

        //支付后的记录处理..

        return true;

    }
}

pageDto类

/**
 * 支付DTO
 */
public class PayDTO {

    /**
     * 支付类型
     */
    private String type;

    /**
     * 支付金额
     */
    private BigDecimal payMoney;

    /**
     * ...........
     */

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public BigDecimal getPayMoney() {
        return payMoney;
    }

    public void setPayMoney(BigDecimal payMoney) {
        this.payMoney = payMoney;
    }

}

这个策略上下文,则是选择策略的入口,这里会进行参数的处理,将这里我就将pageDTO类中的type字符串转换成对应的枚举类。
到这里使用策略模式的编写算是完成了,下面进行编写客户端的代码

客户端代码

支付控制器

@RestController
@RequestMapping("pay")
public class PayController {

    @Autowired
    private PayStrategyContext payStrategyContext;

    @PostMapping
    public boolean pay(@RequestBody PayDTO payDTO){

        //这里因为懒。。就没有加上Service层了,直接在控制器处理
        return payStrategyContext.payHandle(payDTO);
    }
}

效果

新需求

后续新增一个银联的支付方式,我们只需要添加银联的支付策略类和添加银联的支付枚举即可实现

添加银联的支付策略类

/**
 * 银联支付(这里注意我修改了Bean的默认命名)
 */
@Component("unionPayStrategy")
public class UnionPayStrategyImp implements PayStrategy {

    /**
     * 银联支付
     * @return
     */
    @Override
    public boolean pay() {

        //进行银联的支付

        System.out.println("进行银联的支付逻辑");
        return true;
    }

}
复制代码

在枚举类中添加银联的支付枚举

/**
 * 支付策略类型
 */
public enum PayStrategyEnum {
    WECHAT_PAY("wechat","wechatPayStrategy","微信支付"),
    ALIPAY("alipay","alipayStrategy","支付宝支付"),
    UNION_PAY("unionpay","unionPayStrategy","银联支付")
    ;

    /**
     * 支付策略code
     */
    private String code;

    /**
     * bean名称
     */
    private String className;

    /**
     * 信息
     */
    private String info;

    PayStrategyEnum(String code,String className,String info){
        this.code=code;
        this.className=className;
        this.info=info;
    }

    public String getCode() {
        return code;
    }

    public String getClassName() {
        return className;
    }

    public String getInfo() {
        return info;
    }

}

实现效果

以上是我使用Spring boot 运用策略模式实现的效果,如果有误人子弟的地方,望在评论区指出。

到此这篇关于Spring boot 运用策略模式实现,避免多次使用if的文章就介绍到这了,更多相关Spring boot 策略模式内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 实践讲解SpringBoot自定义初始化Bean+HashMap优化策略模式

    策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 传统的策略模式一般是创建公共接口.定义公共方法-->然后创建实体类实现公共接口.根据各自的逻辑重写公共方法-->创建一个行为随着策略对象改变而改变的 context 对象-->根据不同的传参,调用不同的接口实现类方法,达到只改变参数即可获得不同结果的目的. 但是也可以明显发现,这种策略模式的实现方式,代码量较大,而且还要自定义要传递的参数,可能会引入一定数量的if/else,有一定的优

  • 浅谈用SpringBoot实现策略模式

    目录 问题的提出 策略模式代码的实现 进一步的思考 心得体会 问题的提出 阅读别人代码的时候最讨厌遇到的就是大段大段的if-else分支语句,一般来说读到下面的时候就忘了上面在判断什么了.很多资料上都会讲到使用策略模式来改进这种代码逻辑. 策略模式的类图如下: 只需要按照这个图写代码就可以了. 策略模式代码的实现 借助Spring框架我们能够轻松的实现策略模式. 举一个简单的例子,我们去咖啡店买咖啡的时候,会根据自己的喜好和胃容量选择大小杯.那么我们就要实现一个CoffeeStategy: pa

  • Springboot中实现策略模式+工厂模式的方法

    策略模式和工厂模式相信大家都比较熟悉,但是大家有没有在springboot中实现策略和工厂模式? 具体策略模式和工厂模式的UML我就不给出来了,使用这个这两个模式主要是防止程序中出现大量的IF ELSE IF ELSE.....接下来咱们直接实现,项目结构图: 工厂类FactoryStrategy负责创建策略的工厂,代码比较简单,比较关键的一点是AutoWired一个Map<String, Strategy> 这个会在初始化的时候将所有的Strategy自动加载到Map中,是不是很方便.使用c

  • 详解SpringBoot结合策略模式实战套路

    1.1. 前言 我们都知道设计模式好,可以让我们的代码更具可读性,扩展性,易于维护,但大部分程序猿一开始都学过至少一遍设计模式吧,实战中不知用到了几成.接下来让我介绍一个结合SpringBoot的策略模式套路,让你的代码少些if-else 1.2. 开撸 废话不多说,直接告诉你今天的核心是@autowired,看到这个是不是很熟悉,你每天都在用,不就是自动注入Spring管理的Bean吗?但我们对它的用法很多时候就局限在全局变量的注入了,忘记了,它其实还可以构造器注入,类型注入或命名注入,那么结

  • SpringBoot策略模式的实践使用

    前言 在实际业务代码中,我们经常会碰到这样的代码: String type = actualService.getRealtype(uid); if(type.equals("typeA")){ // do func A }else if(type.equals("typeB")){ // do func B }else if(type.equals("typeC")){ // do func C }else[ //... } 这种 if-els

  • Spring boot 运用策略模式实现避免多次使用if的操作代码

    目录 前言 环境配置 实现目标 准备策略接口和具体实现策略类 支付策略接口 微信支付策略类 支付宝支付策略类 准备支付策略上下文Context和支付策略工厂类 支付策略工厂类 支付策略枚举类 支付策略上下文 pageDto类 客户端代码 支付控制器 效果 新需求 添加银联的支付策略类 在枚举类中添加银联的支付枚举 实现效果 前言 这里就不详细去介绍策略模式是怎么样的了,想了解的可以点击下面的链接 策略模式介绍的链接:策略模式的介绍 这里列出策略模式的好处 场景:某网页有个支付,其中包含了微信.支

  • Spring boot + mybatis + Vue.js + ElementUI 实现数据的增删改查实例代码(二)

    在上篇文章给大家介绍了Spring boot + mybatis + Vue.js + ElementUI 实现数据的增删改查实例代码(一),接下来我们添加分页相关的依赖,时间紧张,直接上代码了,贴上我的pom文件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=

  • Spring boot + mybatis + Vue.js + ElementUI 实现数据的增删改查实例代码(一)

    环境搭建 spring boot的简介 以往我们开发时用到spring总是避免不了繁琐的配置,例如我们要配置一个数据库连接,可能需要以下几步: 1.编写jdbc.properties配置文件: 2.创建spring的配置文件,加入spring配置文件前缀.配置数据库连接信息以及sqlsessionFactory等等: 3.还要在web.xml文件中加入spring的监听. springboot的出现大大简化了项目的搭建过程(spring配置以及maven配置),让我们专注于应用功能的开发,而不是

  • Spring boot+mybatis+thymeleaf 实现登录注册增删改查功能的示例代码

    本文重在实现理解,过滤器,业务,逻辑需求,样式请无视.. 项目结构如下 1.idea新建Spring boot项目,在pom中加上thymeleaf和mybatis支持.pom.xml代码如下 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3

  • spring boot 下对JSON返回值去除null和空字段操作

    在开发过程中,我们需要统一返回前端json格式的数据,但有些接口的返回值存在 null或者""这种没有意义的字段. 不仅影响理解,还浪费带宽,这时我们可以统一做一下处理,不返回空字段,或者把NULL转成"",spring 内置的json处理框架是Jackson.我们可以对它配置一下达到目的 直接看代码,很简单. /** * 〈返回json空值去掉null和""〉 〈功能详细描述〉 * * @author gogym * @version 2017

  • 以Spring Boot的方式显示图片或下载文件到浏览器的示例代码

    以Java web的方式显示图片到浏览器以Java web的方式下载服务器文件到浏览器 以Spring Boot的方式显示图片或下载文件到浏览器 请求例子:http://localhost:8080/image/1564550185144.jpeg 示例代码: import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.R

  • Spring Boot如何利用拦截器加缓存完成接口防刷操作

    目录 为什么需要接口防刷 技术解析 主要代码 测试结果 总结 为什么需要接口防刷 为了减缓服务器压力,将服务器资源留待给有价值的请求,防止恶意访问,一般的程序都会有接口防刷设置,接下来介绍一种简单灵活的接口防刷操作 技术解析 主要采用的技术还是拦截+缓存,我们可以通过自定义注解,将需要防刷的接口给标记出来管理,利用缓存统计指定时间区间里,具体的某个ip访问某个接口的频率,如果超过某个阈值,就让他进一会儿小黑屋,到期自动解放 主要代码 前置环境搭建,Spring Boot项目,引入Web和Redi

  • Spring Boot对Future模式的支持详解

    前言 我们在实际项目中有些复杂运算.耗时操作,就可以利用多线程来充分利用CPU,提高系统吞吐量.SpringBoot对多线程支持非常好,对我们的开发非常便捷. Future模式是多线程开发中非常常见的一种设计模式.核心思想是异步调用.当我们执行一个方法时,方法中有多个耗时任务需要同时去做,而且又不着急等待这个结果时可以让客户端立即返回然后,后台慢慢去计算任务. 当我们做一件事的时候需要等待,那么我们就可以在这个等待时间内来去做其它事情,这样就可以充分利用时间.比如我们点外卖,需要一段时间,那么我

  • Spring Boot自定义 Starter并推送到远端公服的详细代码

    目录 一.新建项目,完善pom文件 二.编写业务逻辑 三.编写自动配置类AutoConfig 四.编写spring.factories文件加载自动配置类 五.maven打包 六.推送到远端仓库,使用JitPack 七.使用案例 八.相关问题 一.新建项目,完善pom文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.

  • Spring Boot与RabbitMQ结合实现延迟队列的示例

    背景 何为延迟队列? 顾名思义,延迟队列就是进入该队列的消息会被延迟消费的队列.而一般的队列,消息一旦入队了之后就会被消费者马上消费. 场景一:在订单系统中,一个用户下单之后通常有30分钟的时间进行支付,如果30分钟之内没有支付成功,那么这个订单将进行一场处理.这是就可以使用延时队列将订单信息发送到延时队列. 场景二:用户希望通过手机远程遥控家里的智能设备在指定的时间进行工作.这时候就可以将用户指令发送到延时队列,当指令设定的时间到了再将指令推送到只能设备. 延迟队列能做什么? 延迟队列多用于需

随机推荐