Java面向对象进阶实战:用工厂模式+策略模式优化支付系统

⭐️个体主页:Kidd

📚所属栏目:java

在上一篇实战中,我们基于接口与多态实现了简易支付系统,具备了基础支付、退款功能及良好的扩展性。但在实际开发场景中,仍存在可优化空间:客户端需直接创建具体支付类对象,耦合了具体实现;支付方式切换时需手动注入实例,缺乏统一管理。本文将结合工厂模式与策略模式,对原有支付系统进行升级,进一步降低耦合、提升代码灵活性与可维护性,深化面向对象设计思维的落地。

一、设计模式选型:工厂模式+策略模式

针对原有系统的不足,我们选用两种经典设计模式组合优化,两者分工明确、互补增效:

1.1 工厂模式:封装对象创建逻辑

工厂模式(Factory Pattern)的核心是"封装对象创建过程",由工厂类统一负责创建具体实例,客户端无需关注对象创建的细节,只需通过工厂获取所需实例。适用于解决"对象创建与业务逻辑耦合"问题,对应原有系统中"客户端直接new具体支付类"的痛点。

1.2 策略模式:封装算法(支付方式)家族

策略模式(Strategy Pattern)的核心是"定义一系列算法,将每个算法封装起来,使它们可以相互替换"。通过将不同支付方式(算法)抽象为策略,客户端可根据需求动态切换策略,无需修改原有业务逻辑,与原有系统的多态特性完美契合,同时优化支付方式的管理与切换逻辑。

1.3 组合优势

工厂模式负责"策略对象的创建",策略模式负责"策略的定义、切换与执行",两者结合可实现:客户端无需依赖具体支付类,通过工厂获取策略实例,通过上下文切换策略,完全隔离对象创建与业务执行,符合"开闭原则"与"单一职责原则"。

二、系统优化实现步骤

本次优化基于上一篇的支付系统核心代码(Payment接口、PaymentParam类、各支付实现类),新增工厂类、策略上下文类,调整客户端调用逻辑,不修改原有核心业务逻辑,保证兼容性。

2.1 定义支付方式枚举:统一标识策略

新增支付方式枚举(PayTypeEnum),用于统一标识不同支付策略,避免客户端直接传入字符串导致的错误,同时简化工厂类的逻辑判断。

Plain 复制代码
/**
 * 支付方式枚举:统一标识支付策略
 */
public enum PayTypeEnum {
    ALIPAY("支付宝支付"),
    WECHAT_PAY("微信支付"),
    BANK_CARD_PAY("银行卡支付"),
    UNION_PAY("银联支付");

    // 支付方式描述
    private final String desc;

    PayTypeEnum(String desc) {
        this.desc = desc;
    }

    public String getDesc() {
        return desc;
    }
}

2.2 实现支付策略工厂:封装对象创建

创建支付策略工厂类(PaymentFactory),根据支付方式枚举创建对应支付实例,客户端通过工厂获取实例,无需直接依赖具体支付类。

Plain 复制代码
/**
 * 支付策略工厂:负责创建具体支付策略实例
 */
public class PaymentFactory {
    // 私有构造:防止实例化工厂类
    private PaymentFactory() {}

    // 根据支付方式枚举创建对应支付实例
    public static Payment getPayment(PayTypeEnum payType) {
        switch (payType) {
            case ALIPAY:
                return new Alipay();
            case WECHAT_PAY:
                return new WeChatPay();
            case BANK_CARD_PAY:
                return new BankCardPay();
            case UNION_PAY:
                return new UnionPay();
            default:
                throw new IllegalArgumentException("不支持的支付方式:" + payType);
        }
    }
}

核心优势:若新增支付方式,只需扩展枚举与工厂类的switch分支,客户端调用逻辑无需修改;避免了客户端直接创建具体类,降低耦合。

2.3 优化支付上下文:适配策略模式

对上一篇的PaymentContext进行优化,使其适配策略模式,支持通过支付方式枚举切换策略,同时整合支付参数校验、支付/退款执行逻辑,强化上下文的统一调度能力。

Plain 复制代码
/**
 * 支付策略上下文:统一调度支付策略,支持动态切换
 */
public class PaymentStrategyContext {
    // 持有支付策略引用
    private Payment payment;

    // 构造方法:通过工厂创建策略实例
    public PaymentStrategyContext(PayTypeEnum payType) {
        this.payment = PaymentFactory.getPayment(payType);
    }

    // 动态切换支付策略
    public void switchStrategy(PayTypeEnum payType) {
        this.payment = PaymentFactory.getPayment(payType);
        System.out.println("支付方式切换为:" + payType.getDesc());
    }

    // 统一支付入口:整合参数校验与支付执行
    public String executePay(PaymentParam param) {
        // 前置参数校验
        if (!Payment.validateParam(param)) {
            return "支付失败:支付参数不合法";
        }
        // 执行具体支付策略
        return payment.pay(param);
    }

    // 统一退款入口
    public String executeRefund(PaymentParam param) {
        if (!Payment.validateParam(param)) {
            return "退款失败:参数不合法";
        }
        return payment.refund(param);
    }
}

优化点:上下文不再需要客户端注入支付实例,而是通过工厂自动获取;新增策略切换方法,支持通过枚举快速切换支付方式;前置参数校验逻辑统一整合,减少重复代码。

三、优化后系统测试与验证

创建测试类,模拟客户端调用优化后的支付系统,验证策略创建、切换、支付/退款功能的正确性,对比原有系统体现优化价值。

Plain 复制代码
/**
 * 优化后支付系统测试类(工厂模式+策略模式)
 */
public class OptimizedPaymentSystemTest {
    public static void main(String[] args) {
        // 1. 初始化支付上下文(指定支付方式,工厂自动创建策略)
        PaymentStrategyContext context = new PaymentStrategyContext(PayTypeEnum.ALIPAY);
        // 支付宝支付测试
        PaymentParam alipayParam = new PaymentParam("ORDER2024001", 199.99, "zhangsan@aliyun.com", "123456");
        System.out.println(context.executePay(alipayParam));
        System.out.println(context.executeRefund(alipayParam));
        System.out.println("------------------------");

        // 2. 切换支付方式为微信支付
        context.switchStrategy(PayTypeEnum.WECHAT_PAY);
        PaymentParam weChatParam = new PaymentParam("ORDER2024002", 299.00, "wx123456789", "654321");
        System.out.println(context.executePay(weChatParam));
        System.out.println("------------------------");

        // 3. 切换支付方式为银联支付
        context.switchStrategy(PayTypeEnum.UNION_PAY);
        PaymentParam unionPayParam = new PaymentParam("ORDER2024004", 399.00, "6217001234567890", "333444");
        System.out.println(context.executePay(unionPayParam));
        System.out.println("------------------------");

        // 4. 测试不支持的支付方式
        try {
            new PaymentStrategyContext(PayTypeEnum.valueOf("APPLE_PAY"));
        } catch (IllegalArgumentException e) {
            System.out.println("异常提示:" + e.getMessage());
        }
    }
}

测试结果与分析

Plain 复制代码
支付宝支付成功!订单号:ORDER2024001,金额:199.99元,支付账号:zhangsan@aliyun.com
支付宝退款成功!订单号:ORDER2024001,退款金额:199.99元
------------------------
支付方式切换为:微信支付
微信支付成功!订单号:ORDER2024002,金额:299.00元,微信号:wx123456789
------------------------
支付方式切换为:银联支付
银联支付成功!订单号:ORDER2024004,金额:399.00元,银联卡号:6217001234567890
------------------------
异常提示:不支持的支付方式:APPLE_PAY

结果分析:优化后系统正常支持各类支付、退款功能,支付方式切换更简洁;客户端无需直接创建具体支付类,仅通过枚举与上下文交互,耦合度显著降低;工厂模式统一管理对象创建,策略模式实现算法灵活切换,代码可读性与可维护性大幅提升。

四、新旧系统对比:优化价值凸显

通过工厂模式与策略模式的整合,系统在以下维度实现显著优化,更贴合实际开发需求:

对比维度 原有系统 优化后系统
对象创建 客户端直接new具体支付类,耦合度高 工厂统一创建实例,客户端无感知具体实现
支付方式切换 手动注入新实例,需关注具体类名 通过枚举切换,上下文自动适配,简洁高效
代码冗余 参数校验逻辑分散在各支付类 上下文统一前置校验,减少重复代码
扩展性 新增支付类后,客户端需修改创建逻辑 仅扩展枚举与工厂分支,客户端无感知

五、进阶拓展:工厂模式的进一步优化

当前工厂类采用switch分支判断支付方式,若支付方式过多,分支会变得冗长,可进一步优化为"反射工厂",通过配置文件或注解动态加载支付类,彻底消除switch分支,实现更极致的扩展性。

Plain 复制代码
/**
 * 反射优化版支付工厂:消除switch分支,支持动态扩展
 */
public class ReflectPaymentFactory {
    private ReflectPaymentFactory() {}

    // 配置支付方式与对应类路径(实际可放在配置文件中)
    private static final Map<PayTypeEnum, String> PAY_CLASS_MAP = new HashMap<>();

    // 静态代码块初始化配置
    static {
        PAY_CLASS_MAP.put(PayTypeEnum.ALIPAY, "com.payment.Alipay");
        PAY_CLASS_MAP.put(PayTypeEnum.WECHAT_PAY, "com.payment.WeChatPay");
        PAY_CLASS_MAP.put(PayTypeEnum.BANK_CARD_PAY, "com.payment.BankCardPay");
        PAY_CLASS_MAP.put(PayTypeEnum.UNION_PAY, "com.payment.UnionPay");
    }

    // 反射创建支付实例
    public static Payment getPayment(PayTypeEnum payType) {
        String className = PAY_CLASS_MAP.get(payType);
        if (className == null) {
            throw new IllegalArgumentException("不支持的支付方式:" + payType);
        }
        try {
            // 反射加载类并创建实例
            Class<?> clazz = Class.forName(className);
            return (Payment) clazz.newInstance();
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            throw new RuntimeException("创建支付实例失败", e);
        }
    }
}

优化优势:新增支付方式时,只需添加枚举、配置类路径,无需修改工厂类代码,完全符合"开闭原则";适用于支付方式频繁扩展的场景,灵活性更强。

六、核心总结

本次通过工厂模式与策略模式对支付系统的优化,本质是对面向对象"封装、多态"特性的深度应用,核心价值在于:

  • 工厂模式隔离了"对象创建"与"业务逻辑",降低了客户端与具体实现的耦合,简化了对象管理。

  • 策略模式将不同支付方式封装为独立策略,实现了算法的动态切换与复用,提升了系统的灵活性。

  • 两种模式的组合的并非过度设计,而是针对实际业务痛点的合理优化,使系统更符合企业级开发的规范与需求。

这种设计思路可广泛迁移到日志框架、消息通知、数据解析等多算法场景,通过设计模式的合理运用,将面向对象知识点转化为可落地的高质量代码,提升系统的可扩展性、可维护性与可读性。

相关推荐
heartbeat..2 小时前
网络通信核心知识全解析:模型、协议与 TCP 机制
java·网络·网络协议·tcp/ip
weixin_440730502 小时前
Java基础学习day01
java·开发语言·学习
天远云服3 小时前
Go 语言实战:构建高并发天远“全国自然人人脸比对 V3”微服务网关
java·大数据·微服务·golang
PPPPickup3 小时前
easychat项目复盘---管理端系统设置
java·开发语言·前端
挖矿大亨3 小时前
C++中的this指针
java·开发语言·c++
sheji34163 小时前
【开题答辩全过程】以 共享单车管理系统为例,包含答辩的问题和答案
java
北北~Simple3 小时前
接口调不通的情况
java
Kiyra4 小时前
八股篇(1):LocalThread、CAS和AQS
java·开发语言·spring boot·后端·中间件·性能优化·rocketmq
开心比对错重要4 小时前
进程、线程、虚拟线程详解及线程个数设置
java·jvm·算法·面试