侧边栏壁纸
博主头像
phoenix-blog 博主等级

悄咪咪的,怕发现

  • 累计撰写 16 篇文章
  • 累计创建 23 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

工厂设计模式在Springboot中的实现

phoenix
2025-10-13 / 0 评论 / 0 点赞 / 9 阅读 / 0 字 / 正在检测是否收录...

工厂方法模式:核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。

定义接枚举类

package com.example.db.factory;

import com.example.demo.base.enums.BaseEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 支付方式
 */
@Getter
@AllArgsConstructor
public enum PayType implements BaseEnum<Integer> {
    WECHAT(1, "微信"),
    ALIPAY(2, "支付宝"),
    BANK(3, "银行卡"),
    ;

    private final Integer value;
    private final String desc;
}

定义抽象类(抽象类中主要是公用方法的实现(一般定义为protected))

package com.example.db.factory;

import lombok.RequiredArgsConstructor;

/**
 * 主要实现子类的公共静态方法和公用方法
 */
@RequiredArgsConstructor
public abstract class PayAbstractService {

    private final PayType type;

    /**
     * 公共静态方法
     */
    protected static String getInnerData(){
        return "内部静态数据";
    }

    /**
     * 公共实体方法
     */
    protected String getInnerDataDy(){
        return "内部动态数据" + type.getDesc();
    }

    /**
     * 获取支付方式
     *
     * @return 支付方式
     */
    public abstract PayType getPayType();

    /**
     * 支付
     *
     * @param orderId 订单id
     * @return 支付结果
     */
    public abstract String pay(String orderId);
}

定义具体类(通过枚举来是区分)

wechat

package com.example.db.factory.impl;

import com.example.db.factory.PayAbstractService;
import com.example.db.factory.PayType;
import org.springframework.stereotype.Component;

@Component
public class WeChatPayServiceImpl extends PayAbstractService {
    private static final PayType type = PayType.WECHAT;

    public WeChatPayServiceImpl() {
        super(type);
    }

    @Override
    public PayType getPayType() {
        return type;
    }

    @Override
    public String pay(String orderId) {
        return "wechat--" + getInnerData() +"-"+ orderId +"-"+ getInnerDataDy();
    }

    public String weChatMethod(){
        return "weChatMethod--";
    }
}

alipay

package com.example.db.factory.impl;

import com.example.db.factory.PayAbstractService;
import com.example.db.factory.PayType;
import org.springframework.stereotype.Component;

@Component
public class AliPayServiceImpl extends PayAbstractService {
    private static final PayType type = PayType.ALIPAY;

    public AliPayServiceImpl() {
        super(type);
    }

    @Override
    public PayType getPayType() {
        return type;
    }

    @Override
    public String pay(String orderId) {
        return "aliPay--" + getInnerData() +"-"+ orderId +"-"+ getInnerDataDy();
    }
}

bank

package com.example.db.factory.impl;

import com.example.db.factory.PayAbstractService;
import com.example.db.factory.PayType;
import org.springframework.stereotype.Component;

@Component
public class BankPayServiceImpl extends PayAbstractService {
    private static final PayType type = PayType.BANK;

    public BankPayServiceImpl() {
        super(type);
    }

    @Override
    public PayType getPayType() {
        return type;
    }

    @Override
    public String pay(String orderId) {
        return "bank--" + getInnerData() +"-"+ orderId +"-"+ getInnerDataDy();
    }
}

springboot中在工厂中注册定义的类(这里按照需求是注册以一个还是全部注册根据业务需求来安排)

package com.example.db.factory;

import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * pay factory
 */
@Component
public class PayFactory implements ApplicationContextAware, InitializingBean {

    private static final Map<PayType, PayAbstractService> payMap = new ConcurrentHashMap<>();
    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void afterPropertiesSet() {
        // 在初始化阶段,收集Spring容器中所有Payment类型的Bean
        Map<String, PayAbstractService> beansOfType = applicationContext.getBeansOfType(PayAbstractService.class);
        beansOfType.values().forEach(payment -> payMap.put(payment.getPayType(), payment));
    }

    // 获取支付类型
    public static PayAbstractService getPay(PayType payType) {
        return payMap.get(payType);
    }
}


使用(通过枚举来选择具体实现类)

package com.example.db.factory;

import com.example.db.factory.impl.WeChatPayServiceImpl;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class PayFactoryTest {

    @Test
    public void test1() {
        PayAbstractService pay1 = PayFactory.getPay(PayType.ALIPAY);
        System.out.println(pay1.pay("1"));
        PayAbstractService pay2 = PayFactory.getPay(PayType.BANK);
        System.out.println(pay2.pay("2"));
        PayAbstractService pay3 = PayFactory.getPay(PayType.WECHAT);
        System.out.println(pay3.pay("3"));

        // 向下强转后调用具体实现类方法
        WeChatPayServiceImpl pay4 = (WeChatPayServiceImpl) pay3;
        System.out.println(pay4.weChatMethod());
    }
}


aliPay--内部静态数据-1-内部动态数据支付宝
bank--内部静态数据-2-内部动态数据银行卡
wechat--内部静态数据-3-内部动态数据微信
weChatMethod--

注意点

这里我把接口的功能放到抽象类,可以根据自己的习惯拆开,将抽象接口换成接口,方便阅读

公共常量统一放在抽象类中,如果不同的枚举有自己独立的数据则可以使用枚举类存储

获取类型改成静态方法,通过静态方法直接获取数据,不需要通过注入来获取子类bean

0

评论区