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;

重新测试

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

相关推荐
Sunsets_Red11 小时前
待修改莫队与普通莫队优化
java·c++·python·学习·算法·数学建模·c#
葡萄城技术团队11 小时前
在 Java 中优化 MySQL 查询以提升性能
java·开发语言·mysql
杀死那个蝈坦11 小时前
短链接生成-基于布隆过滤器和唯一索引
java·数据库·微服务·oracle·rocketmq
慕白Lee11 小时前
Java foreach在lambda的foreach遍历中退出操作(lambda foreach break)
java
winfield82111 小时前
Java 中大量闲置 MySQL 连接的解决方案(从根因到落地)
java·mysql
moxiaoran575311 小时前
Java开发中VO的使用
java·开发语言
计算机毕设指导611 小时前
基于微信小程序图像识别的智能垃圾分类系统【源码文末联系】
java·spring boot·mysql·微信小程序·小程序·分类·maven
LJianK112 小时前
前后端接口常见传参
java·spring
独自破碎E12 小时前
消息队列如何保证消息的有效性?
java·开发语言·rocketmq·java-rocketmq
38242782712 小时前
使用 webdriver-manager配置geckodriver
java·开发语言·数据库·爬虫·python