工厂方法模式:核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
定义接枚举类
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);
}
定义具体类(通过枚举来是区分)
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
评论区