背景
有一个支付的功能,他包含可以选择支付渠道(微信、支付宝)、支付方式(余额、银行卡),如下图:
基本做法
public static void main(String[] args) {
Integer type=0;
Integer mode=0;
if (type== 0){//微信
if (mode ==0){//余额
//todo
}else if (mode == 1){//银行卡
//todo
}
}else if (type== 1){//支付宝
if (mode ==0){//余额
//todo
}else if (mode == 1){//银行卡
//todo
}
}
}
上面的if/esle看着是不是很烦人,如果业务复杂,这样写出来的代码很难维护和扩展。
换个思路
1、我们先定义一些基本的类
支付渠道--枚举:
public enum PayTypeEnum {
WX("微信",0),
ALIPAY("支付宝",1);
private String name;
private Integer value;
PayTypeEnum(String name,Integer value){
this.name=name;
this.value=value;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setValue(Integer value) {
this.value = value;
}
public Integer getValue() {
return value;
}
}
支付方式--枚举:
public enum PayModeEnum {
BALANCE("余额",0),
BANK_CARD("银行卡",1);
private String name;
private Integer value;
PayModeEnum(String name,Integer value){
this.name=name;
this.value=value;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setValue(Integer value) {
this.value = value;
}
public Integer getValue() {
return value;
}
}
常量:
public class CommConstant {
public static String ORDER_ID="orderId";
/***
* 支付渠道的key
*/
public static String TYPE="type";
/**
* 支付方式的key
*/
public static String MODE="mode";
}
异常类
public class ThirdErrorException extends RuntimeException{
public ThirdErrorException() {
}
public ThirdErrorException(String message) {
super(message);
}
public ThirdErrorException(String message, Throwable cause) {
super(message, cause);
}
}
public class ParamErrorException extends RuntimeException{
public ParamErrorException() {
}
public ParamErrorException(String message) {
super(message);
}
public ParamErrorException(String message, Throwable cause) {
super(message, cause);
}
}
public class BusinessException extends RuntimeException{
public BusinessException() {
}
public BusinessException(String message) {
super(message);
}
public BusinessException(String message, Throwable cause) {
super(message, cause);
}
}
2、我们接下来定义支付
public interface PayExecutor {
/**
* 支付渠道
* @return
*/
PayTypeEnum support();
/**
* 执行支付
* @param param
*/
void doPayExecutor(Map<String,Object> param);
}
3、定义支付方式
public interface PayProcessor {
/**
* 支付方式
* @return
*/
PayModeEnum supportMode();
/**
* 支付渠道
* @return
*/
PayTypeEnum supportType();
/**
* 支付检查参数
* @param param
*/
void checkParam(Map<String,Object> param);
/**
* 执行支付
* @param param
*/
void payProcessor(Map<String,Object> param);
}
4、抽象一个支付方式,用来扩展使用
public abstract class AbstractPayProcessor implements PayProcessor{
/**
* 这里可以写一些前置的校验或者通用的处理逻辑
* @param param
* @throws ParamErrorException
* @throws ThirdErrorException
*/
void preProcessor(Map<String,Object> param) throws ParamErrorException, ThirdErrorException {
String orderId = MapUtils.getString(param, CommConstant.ORDER_ID);
if (StringUtils.isBlank(orderId)){
throw new ParamErrorException("订单id不能为空!");
}
}
}
5、定义一个抽象的支付,扩展使用
public abstract class AbstractApyExecutor implements PayExecutor {
/**
* 选择支付方式
* @param payProcessorList
* @param map
* @return
*/
public PayProcessor select(List<PayProcessor> payProcessorList,Map<String, Object> map){
Integer mode = MapUtils.getInteger(map, CommConstant.MODE);
Integer type = MapUtils.getInteger(map, CommConstant.TYPE);
Optional<PayProcessor> first = payProcessorList.stream()
.filter(t -> t.supportMode().getValue().equals(mode) && t.supportType().getValue().equals(type) ).
collect(Collectors.toList()).stream().findFirst();
if (first.isPresent()){
return first.get();
}
return null;
}
}
6、下面我们就可实现每种支付渠道的获取
1)微信
@Service
public class WXPayExecutor extends AbstractApyExecutor{
@Autowired
private List<PayProcessor> payProcessorList;
@Override
public PayTypeEnum support() {
return PayTypeEnum.WX;
}
/**
* 支付过程
* @param param
*/
@Override
public void doPayExecutor(Map<String, Object> param) {
PayProcessor payProcessor= select(payProcessorList,param);
payProcessor.checkParam(param);
payProcessor.payProcessor(param);
System.out.println("WXPayExecutor");
}
}
2)支付宝
@Service
@Slf4j
public class ALIPayExecutor extends AbstractApyExecutor{
@Autowired
private List<PayProcessor> payProcessorList;
@Override
public PayTypeEnum support() {
return PayTypeEnum.ALIPAY;
}
@Override
public void doPayExecutor(Map<String, Object> param) {
PayProcessor payProcessor= select(payProcessorList,param);
payProcessor.checkParam(param);
payProcessor.payProcessor(param);
}
}
7、下面我们就可以编写具体的每种支付方式的实现了
1)微信余额
@Service
public class WXBalancePayProcessor extends AbstractPayProcessor {
@Override
public PayModeEnum supportMode() {
return PayModeEnum.BALANCE;
}
@Override
public PayTypeEnum supportType() {
return PayTypeEnum.WX;
}
@Override
public void checkParam(Map<String, Object> param) {
preProcessor(param);
System.out.println("WXBalancePayProcessor checkParam*****");
}
@Override
public void payProcessor(Map<String, Object> param) {
System.out.println("WXBalancePayProcessor payProcessor*****");
}
@Override
void preProcessor(Map<String, Object> param) throws ParamErrorException, ThirdErrorException {
System.out.println("**********");
}
}
2)微信的银行卡
@Service
public class WXBankCardPayProcessor extends AbstractPayProcessor {
@Override
public PayModeEnum supportMode() {
return PayModeEnum.BANK_CARD;
}
@Override
public PayTypeEnum supportType() {
return PayTypeEnum.WX;
}
@Override
public void checkParam(Map<String, Object> param) {
preProcessor(param);
System.out.println("WXBankCardPayProcessor checkParam*****");
}
@Override
public void payProcessor(Map<String, Object> param) {
System.out.println("WXBankCardPayProcessor payProcessor*****");
}
}
3)支付宝的余额
@Service
public class ALIBalancePayProcessor extends AbstractPayProcessor {
@Override
public PayModeEnum supportMode() {
return PayModeEnum.BALANCE;
}
@Override
public PayTypeEnum supportType() {
return PayTypeEnum.ALIPAY;
}
@Override
public void checkParam(Map<String, Object> param) {
preProcessor(param);
System.out.println("ALIBalancePayProcessor checkParam*****");
}
@Override
public void payProcessor(Map<String, Object> param) {
System.out.println("ALIBalancePayProcessor payProcessor*****");
}
}
4)支付宝的银行卡
@Service
public class ALIBankCardPayProcessor extends AbstractPayProcessor {
@Override
public PayModeEnum supportMode() {
return PayModeEnum.BANK_CARD;
}
@Override
public PayTypeEnum supportType() {
return PayTypeEnum.ALIPAY;
}
@Override
public void checkParam(Map<String, Object> param) {
preProcessor(param);
System.out.println("ALIBankCardPayProcessor checkParam*****");
}
@Override
public void payProcessor(Map<String, Object> param) {
System.out.println("ALIBankCardPayProcessor payProcessor*****");
}
}
8、实现一个抽象的支付service
public abstract class AbstractApyService {
/**
* 选择器,选择支付渠道
* @param payExecutorList
* @param map
* @return
*/
public PayExecutor select(List<PayExecutor> payExecutorList,Map<String, Object> map){
Integer type = MapUtils.getInteger(map, CommConstant.TYPE);
Optional<PayExecutor> first = payExecutorList.stream().filter(t -> t.support().getValue().equals(type)).
collect(Collectors.toList()).stream().findFirst();
if (first.isPresent()){
return first.get();
}
return null;
}
}
9、编写一个支付service
@Service
@Slf4j
public class PayService extends AbstractApyService{
@Autowired
private List<PayExecutor> payExecutorList;
/**
* 支付
* @param map
*/
public void pay(Map<String, Object> map){
try {
PayExecutor select = select(payExecutorList,map);
select.doPayExecutor(map);
//通过不同的异常处理不同的业务情况
}catch (ParamErrorException e){//参数异样
//todo
throw new BusinessException(e.getMessage());
}catch (ThirdErrorException e){//调用第三方异常
//todo
throw new BusinessException(e.getMessage());
}
}
}
10、我们再写一个controller测试下
@RestController
@Slf4j
public class PayController {
@Autowired
private PayService payService;
@RequestMapping("/pay")
public ResultWrapper pay(@RequestBody Map<String,Object> map){
log.info("pay param={}", JSON.toJSONString(map));
try {
payService.pay(map);
return ResultWrapper.getSuccessReturn(map);
}catch (BusinessException e){
log.error("pay BusinessException error={}",e.getMessage());
return ResultWrapper.getFailure(e.getMessage());
}catch (Exception e){
log.error("pay error",e);
return ResultWrapper.getFailure("操作失败,请检查后重试!");
}
}
}
11、测试
1)微信余额
后台打印:
2)微信的银行卡
后台打印:
3)支付宝的余额
后台打印:
总结
以上就是我们这次对if/else的改造,看上去代码变多了一些,但是可扩展性和可维护性变强了,并且创建了多个异常类,可以通过不同的异常,处理不同的响应结果,我们要根据业务场景选择合适的处理方式,如果业务简单,可以继续用简单的if/else实现,简单又方便,业务复杂多变,建议使用扩展性和维护性好的。
评论区