springboot下使用最常用的【策略设计模式】优雅干掉if else!!!

7 篇文章 14 订阅
3 篇文章 0 订阅

推荐好文:
2.5万字详解23种设计模式

2.5万字讲解DDD领域驱动设计,从理论到实践掌握DDD分层架构设计

微服务springcloud环境下基于Netty搭建websocket集群实现服务器消息推送----netty是yyds

一、且看代码中令人头疼的if esle

先举一个例子,淘宝购物支付的时候,我们可以选择多种支付方式,如下

public class PayDemo {

public String pay(String payType) {

    String pay = "";
    if ("1".equals(payType)) {
        pay = "账户余额支付";
    } else if ("2".equals(payType)) {
        pay = "余额宝支付";
    } else if ("3".equals(payType)) {
        pay = "花呗支付";
    } else if ("4".equals(payType)) {
        pay = "银行卡支付";
    } else {
        pay = "其他支付";
    }

    System.out.println(pay);
    return pay;
}

}
像这样的if…else控制语句,代码里滥用会大大降低代码的可读性、可维护性、可扩展性以及灵活性,进而使整个软件系统造成危害。因为在实际的项目中,需求往往是不断变化的,新需求也层出不穷,因此违反了违反单一职责原则和开闭原则,而且有些公司的代码审查会通不过。所以,if else的替代方案是很有必要的,如卫语句,枚举,工厂模式,策略模式,状态模式等等。

二、且看我破你

(1)针对于方法级别的if else,使用枚举,工厂模式,策略模式等方案破解,点击下方的阅读原文可以查看CSDN的原文。

(2)针对于类级别的if else在业务复杂的时候是最常用的,使用策略模式破解如下,牢记四步走战略

1. 首先定义一个枚举:

/**
 * 支付类型枚举
 * @Author WDYin
 * @Date 2022/4/16
 **/
@Getter
public enum PayTypeEnum {

    BALANCE("1","账户余额支付"),
    YU_E_BAO("2","余额宝支付"),
    HUA_BEI("3","花呗支付"),
    BANK("4","银行卡支付");
    
    private String code;
    private String value;

    PayTypeEnum(String code,String value) {
        this.code = code;
        this.value = value;
    }
}

2. 定义一个支付接口

/**
 * 支付接口
 * @Author WDYin
 * @Date 2022/4/16
 **/
public interface Pay {

    /**
     * 获取支付类型
     * @return
     */
    PayTypeEnum getPayType();

    /**
     * 定义支付方法
     */
    void pay();
}

3. 定义四个类实现支付接口

(1)账户余额支付类

/**
 * 账户余额支付
 * @Author WDYin
 * @Date 2022/4/16
 **/
@Service
public class BalancePay implements Pay {

    /**
     * 设置账户余额类型
     * @return
     */
    @Override
    public PayTypeEnum getPayType() {
        return PayTypeEnum.BALANCE;
    }

    /**
     * 账户余额支付逻辑
     */
    @Override
    public void pay() {
        System.out.println(getPayType().getValue());
    }
}

(2)余额宝支付类


/**
 * 余额宝支付
 * @Author WDYin
 * @Date 2022/4/16
 **/
@Service
public class YuEBaoPay implements Pay {

    /**
     * 设置余额宝支付类型
     * @return
     */
    @Override
    public PayTypeEnum getPayType() {
        return PayTypeEnum.YU_E_BAO;
    }

    /**
     * 余额宝支付逻辑
     */
    @Override
    public void pay() {
        System.out.println(getPayType().getValue());
    }
}

(3)花呗支付类


/**
 * 花呗支付
 * @Author WDYin
 * @Date 2022/4/16
 **/
@Service
public class HuaBeiPay implements Pay {

    /**
     * 设置花呗支付类型
     * @return
     */
    @Override
    public PayTypeEnum getPayType() {
        return PayTypeEnum.HUA_BEI;
    }

    /**
     * 花呗支付逻辑
     */
    @Override
    public void pay() {
        System.out.println(getPayType().getValue());
    }
}

(4)银行卡支付类

/**
 * 银行卡支付
 * @Author WDYin
 * @Date 2022/4/16
 **/
@Service
public class BankPay implements Pay {

    /**
     * 设置银行卡支付类型
     * @return
     */
    @Override
    public PayTypeEnum getPayType() {
        return PayTypeEnum.BANK;
    }

    /**
     * 银行卡支付逻辑
     */
    @Override
    public void pay() {
        System.out.println(getPayType().getValue());
    }
}

4. 定义上下文环境对象

/**
 * 支付上下文环境对象
 * @Author WDYin
 * @Date 2022/4/16
 **/
@Service
public class PayContext {

    /**
     * payMap容器存储支付类型和支付类的映射关系
     * 此map可以使用框架Guava或者Caffine
     */
    private final Map<String, Pay> payMap = new ConcurrentHashMap<>();

    /**
     * 注入spring容器对象
     */
    @Autowired
    private ApplicationContext applicationContext;

    /**
     * 初始化payMap容器
     * PostConstruct:该注解的方法在项目启动的时候执行这个方法,
     * 也就是在spring容器启动的时候执行.
     */
    @PostConstruct
    private void init() {
        /**
         * 从spring容器中获取所有pay类型的Bean
         */
        Map<String, Pay> beanMap = applicationContext.getBeansOfType(Pay.class);
        /**
         * 存入map集合
         */
        beanMap.forEach((key, value) -> payMap.put(value.getPayType().getCode(), value));
    }

    /**
     * 使用时调用该支付方法即可
     * @param payType
     */
    public void pay(String payType){
        payMap.get(payType).pay();
    }
}

5. 测试

/**
 * @Author WDYin
 * @Date 2021/12/2
 * @Description
 **/
@RunWith(value = SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class SpringbootPayTest {

    @Autowired
    private PayContext payContext;

    @Test
    public void test(){
        payContext.pay(PayTypeEnum.BALANCE.getCode());
    }
}

结果如下:

在这里插入图片描述
在这里插入图片描述

三、总结

如果后续有新的支付方式只需要在枚举加入对应的类型和创建新的支付类实现pay接口,完全不用动其他的类,满足了开闭原则,此方案提高了扩展性,可维护性,还有代码逼格,完全通过了公司的代码检查!
更多优化if else的方式,大家可以看这篇文章!
代码中如何干掉太多的if else即if else的多种替代方案

如果看到这里,说明你喜欢这篇文章,请转发,点赞。关注【微信公众号】微信搜索【老板来一杯java】回复【进群】即可进入无广告交流群!【进群】即可获取【java基础经典面试】一份!和【DDD领域驱动设计实战落地解惑】PDF一份!

好文推荐:
MySQL查询语句执行顺序以及各关键字的详解,并实战分组后每组显示前几条数据
微服务 分布式 集群 负载均衡详述
SpringCloud核心组件概述(五大神兽)

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王德印

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值