Java设计模式 | 基于订单批量支付场景,对策略模式和简单工厂模式进行简单实现

基于订单批量支付场景,对策略模式和简单工厂模式进行简单实现

文章目录

策略模式

介绍

以下是菜鸟教程对策略模式的介绍: 策略模式

在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。

策略模式主要有三个角色:

  • 抽象策略(Abstract Strategy):定义了策略对象的公共接口或抽象类,规定了具体策略类必须实现的方法。
  • 具体策略(Concrete Strategy):实现了抽象策略定义的接口或抽象类,包含了具体的算法实现。
  • 环境(Context):维护一个对策略对象的引用,负责将客户端请求委派给具体的策略对象执行。环境类可以通过依赖注入、简单工厂等方式来获取具体策略对象。

实现

抽象策略

我们使用接口来实现抽象策略,规定了支付的公共方法,根据传入的用户名和支付金额进行结算。

java 复制代码
package knowledege.designPattern.strategy.test1;

import java.math.BigDecimal;

public interface PayStrategy {
    void pay(String name, BigDecimal money);
}

具体策略

初始化微信和支付宝两种支付策略

1.AliPayStrategy
java 复制代码
package knowledege.designPattern.strategy.test1;

import java.math.BigDecimal;

public class AliPayStrategy implements PayStrategy{
    @Override
    public void pay(String name, BigDecimal money) {
        System.out.println("[" +name+ "]使用支付宝支付..." + money + "元");
    }
}
2.WeChatPayStrategy
java 复制代码
package knowledege.designPattern.strategy.test1;

import java.math.BigDecimal;

public class WeChatPayStrategy implements PayStrategy{
    @Override
    public void pay(String name, BigDecimal money) {
        System.out.println("[" +name+ "]使用微信支付..." + money + "元");
    }
}

环境

提供设置策略和执行策略的方法

java 复制代码
package knowledege.designPattern.strategy.test1;

import java.math.BigDecimal;
public class PayContext {
    private PayStrategy payStrategy;
    public PayContext(){}
    public void setPayStrategy(PayStrategy payStrategy){
        this.payStrategy = payStrategy;
    }
    public void executePayStrategy(String name, BigDecimal money){
        payStrategy.pay(name, money);
    }
}

使用简单工厂来获取具体策略对象

支付方式枚举

定义枚举并支持静态根据支付方式获取枚举

java 复制代码
package knowledege.designPattern.strategy.test1;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum PayWayEnum {

    PAY_ALI("01","支付宝"),
    PAY_WE_CHAT("02","微信");
    public final String payWay;
    public final String payDesc;

    public static PayWayEnum getEnumByWay(String payWay){
        for(PayWayEnum enums: PayWayEnum.values()){
            if(enums.payWay.equals(payWay)){
                return enums;
            }
        }
        return null;
    }
}

策略工厂接口

java 复制代码
public interface StrategyFactory {
    PayStrategy initStrategy();
}

策略工厂实现

java 复制代码
package knowledege.designPattern.strategy.test1;

import java.util.Objects;

public class StrategySimpleFactory {
    public static PayStrategy initStrategy(String payWay){
        PayWayEnum payWayEnum = PayWayEnum.getEnumByWay(payWay);
        if (Objects.isNull(payWayEnum)) {
            return null;
        }
        PayStrategy strategy = null;
        switch (payWayEnum) {
            case PAY_ALI:
                strategy = new AliPayStrategy();
                break;
            case PAY_WE_CHAT:
                strategy = new WeChatPayStrategy();
                break;
        }
        return strategy;
    }
}

测试使用

订单实体类

java 复制代码
package knowledege.designPattern.strategy.test1;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrderTestDTO {
    Integer orderNum;
    String payPersonName;
    String payWay;
    BigDecimal payMoney;
}

对订单进行批量支付

模拟对订单进行批量支付

  • 模拟获取一批订单
  • 循环订单进行支付
    • 根据订单的支付方式,获取支付枚举
    • 根据枚举,使用工厂模式获取支付策略
    • 根据策略,使用支付环境进行支付
java 复制代码
package knowledege.designPattern.strategy.test1;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class test1 {
    public static void main(String[] args) {
        List<OrderTestDTO> orderList = initOrders();
        batchPay(orderList);
    }

    /**
     * 获取订单
     */
    public static  List<OrderTestDTO> initOrders(){
        List<OrderTestDTO> orderList = new ArrayList<>();
        orderList.add(new OrderTestDTO(1,"aaa","01",new BigDecimal("99")));
        orderList.add(new OrderTestDTO(2,"aaa","02",new BigDecimal("20")));
        orderList.add(new OrderTestDTO(3,"bbb","01",new BigDecimal("17")));
        orderList.add(new OrderTestDTO(4,"ccc","02",new BigDecimal("19.88")));

        return orderList;
    }

    /**
     * 订单批量支付
     */
    public static void batchPay(List<OrderTestDTO> orderList){
        PayContext payContext = new PayContext();
        orderList.forEach( order -> {
            PayStrategy strategy = StrategySimpleFactory.initStrategy(order.getPayWay());
            payContext.setPayStrategy(strategy);
            payContext.executePayStrategy(order.getPayPersonName(), order.getPayMoney());
        });
    }
}

结果

可以看到每笔订单都成功根据其支付方式支付了。

扩展一种支付方式:银行卡支付

如果需要扩展一种支付方式,才能看出策略+工厂模式的真正优点。

下面我们模拟扩展一种支付方式:银行卡支付

支付策略新增

java 复制代码
package knowledege.designPattern.strategy.test1;

import java.math.BigDecimal;

public class CardStrategy implements PayStrategy{

    @Override
    public void pay(String name, BigDecimal money) {
        System.out.println("[" +name+ "]使用银行卡支付..." + money + "元");
    }
}

支付枚举新增

java 复制代码
PAY_CARD("03","银行卡"),

工厂新增生产银行卡

java 复制代码
            case PAY_CARD:
                strategy = new CardStrategy();
                break;

重新测试

成功适配了银行卡支付,改动较少,又没有更改核心的支付逻辑,符合开闭原则!

相关推荐
考虑考虑3 小时前
Jpa使用union all
java·spring boot·后端
用户3721574261354 小时前
Java 实现 Excel 与 TXT 文本高效互转
java
浮游本尊5 小时前
Java学习第22天 - 云原生与容器化
java
渣哥6 小时前
原来 Java 里线程安全集合有这么多种
java
间彧6 小时前
Spring Boot集成Spring Security完整指南
java
间彧7 小时前
Spring Secutiy基本原理及工作流程
java
数据智能老司机7 小时前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
Java水解8 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
数据智能老司机9 小时前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
洛小豆10 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试