【日常业务开发】策略+工厂模式优化 if...else判断逻辑

场景

业务中经常有支付业务,项目刚开始所有业务使用支付宝支付,后面湖南地区需要使用微信支付,然后湖北又需要使用易宝支付,后期可能还有扩展。如果使用if…else逻辑,业务中经常要写的代码:

public static void pay() {
    
    
    // String fruit = "aliPay";
    // String fruit = "yiBaoPay";
    String payType = "weiXinPay";
    if ("aliPay".equals(payType)){
    
    
        log.info("===调用支付宝接口发起支付业务===");
    } else if ("yiBaoPay".equals(payType)){
    
    
        log.info("===调用易宝接口发起支付业务===");
    } else {
    
    
        log.info("===调用微信接口发起支付业务===");
    }
}

如何优雅的处理消除if…else逻辑,方面后期扩展呢?策略+工厂模式优化

策略+工厂模式优化

在这里插入图片描述

利用Spring自动注入的特点处理

支付接口IPay和具体实现类AliPay、WeiXinPay、YiBaoPay

public interface IPay {
    
    
    String pay();
}

@Service
@Slf4j
public class AliPay implements IPay {
    
    

    @Override
    public String pay() {
    
    
        log.info("===调用支付宝接口发起支付业务===");
        return "调用支付宝接口发起支付业务";
    }
}

@Service
@Slf4j
public class WeiXinPay implements IPay {
    
    
    @Override
    public String pay() {
    
    
        log.info("===调用微信接口发起支付业务===");
        return "调用微信接口发起支付业务";
    }
}

@Service
@Slf4j
public class YiBaoPay implements IPay {
    
    
    @Override
    public String pay() {
    
    
        log.info("===调用易宝接口发起支付业务===");
        return "调用易宝接口发起支付业务";
    }
}

工厂类PayFactory

@Component
public class PayFactory {
    
    
    /**
     * 利用Spring自动注入的特点。Key为bean的名称、value为IPay接口对应的bean实现类
     */
    @Autowired
    Map<String, IPay> map;

    public  IPay getInstance(String type) {
    
    
        return map.get(type);
    }
}
@RestController
public class PayController {
    
    

    @Autowired
    private PayFactory payFactory;

    @GetMapping("/alipay")
    public String aliPay(String type) {
    
    
        IPay pay = payFactory.getInstance(type);
        return pay.pay();
    }
}

Key为bean的名称、value为IPay接口对应的bean实现类。对应的业务类型不好扩展

继承InitializingBean+静态工厂方法调用处理

public interface IPay extends InitializingBean {
    
    
    String pay();
}


@Service
@Slf4j
public class AliPay implements IPay {
    
    

    @Override
    public String pay() {
    
    
        log.info("===调用支付宝接口发起支付业务===");
        return "调用支付宝接口发起支付业务";
    }

    @Override
    public void afterPropertiesSet() throws Exception {
    
    
        PayFactory.registerHandler("ali", this);
    }
}

@Service
@Slf4j
public class WeiXinPay implements IPay {
    
    
    @Override
    public String pay() {
    
    
        log.info("===调用微信接口发起支付业务===");
        return "调用微信接口发起支付业务";
    }

    @Override
    public void afterPropertiesSet() throws Exception {
    
    
        PayFactory.registerHandler("weixin", this);
    }
}

@Service
@Slf4j
public class YiBaoPay implements IPay {
    
    
    @Override
    public String pay() {
    
    
        log.info("===调用易宝接口发起支付业务===");
        return "调用易宝接口发起支付业务";
    }

    @Override
    public void afterPropertiesSet() throws Exception {
    
    
        PayFactory.registerHandler("yibao", this);
    }
}

工厂类PayFactory,暴露注册bean到工厂容器Map对象方法,提供根据type类型查询bean的静态方法

public class PayFactory {
    
    
    private static final Map<String, IPay> PAY_MAP = new HashMap<>();
    /**
     * 获取对应实例Bean
     * @param type
     * @return
     */
    public static IPay getInstance(String type) {
    
    
        return PAY_MAP.get(type);
    }

    /**
     * 注册bean到工厂容器对象
     * @param handlerName
     * @param pay
     */
    public static void registerHandler(String handlerName, IPay pay) {
    
    
        PAY_MAP.put(handlerName, pay);
    }
}

注解+CommandLineRunner+ApplicationContextAware处理/ApplicationListener<ContextRefreshedEvent>

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface PayCode {
    
    
    String value();
    String name();
}

public interface IPay {
    
    
    String pay();
}

@PayCode(value = "alia", name = "支付宝支付")
@Service
@Slf4j
public class AliPay implements IPay {
    
    

    @Override
    public String pay() {
    
    
        log.info("===调用支付宝接口发起支付业务===");
        return "调用支付宝接口发起支付业务";
    }
}

@PayCode(value = "weixin", name = "微信支付")
@Service
@Slf4j
public class WeiXinPay implements IPay {
    
    
    @Override
    public String pay() {
    
    
        log.info("===调用微信接口发起支付业务===");
        return "调用微信接口发起支付业务";
    }
}

@PayCode(value = "yibao", name = "易宝支付")
@Service
@Slf4j
public class YiBaoPay implements IPay {
    
    
    @Override
    public String pay() {
    
    
        log.info("===调用易宝接口发起支付业务===");
        return "调用易宝接口发起支付业务";
    }
}

第一种方式: 工厂类PayFactory实现Spring生命周期函数在run方法中处理被标记的@PayCode的bean对象加入到静态容器Map中:

  • CommandLineRunner:当前Bean被IOC容器装配完成调用run()方法

  • ApplicationContextAware: 获取容器对象ApplicationContext

@Component
public class PayFactory implements CommandLineRunner, ApplicationContextAware {
    
    

    private ApplicationContext applicationContext;

    private static final Map<String, IPay> PAY_MAP = new HashMap<>();

    /**
     * 获取对应实例Bean
     * @param type
     * @return
     */
    public static IPay getInstance(String type) {
    
    
        return PAY_MAP.get(type);
    }


    @Override
    public void run(String... args) throws Exception {
    
    
        Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(PayCode.class);
        if (beansWithAnnotation !=null ) {
    
    
            beansWithAnnotation.forEach((k,v)->{
    
    
                PayCode payCodeAnn = v.getClass().getAnnotation(PayCode.class);
                PAY_MAP.put(payCodeAnn.value(), (IPay)v);
            });
        }
    }

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

第二种方式: 实现ApplicationListener<ContextRefreshedEvent>监听事件接口代替CommandLineRunner, ApplicationContextAware

ContextRefreshedEvent事件: ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在ConfigurableApplicationContext接口中使用 refresh()方法来发生。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用。

@Component
public class PayFactory implements ApplicationListener<ContextRefreshedEvent> {
    
    

    private static final Map<String, IPay> PAY_MAP = new HashMap<>();

    /**
     * 获取对应实例Bean
     * @param type
     * @return
     */
    public static IPay getInstance(String type) {
    
    
        return PAY_MAP.get(type);
    }
    
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
    
    
        ApplicationContext applicationContext = event.getApplicationContext();
        Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(PayCode.class);
        if (beansWithAnnotation !=null ) {
    
    
            beansWithAnnotation.forEach((k,v)->{
    
    
                PayCode payCodeAnn = v.getClass().getAnnotation(PayCode.class);
                PAY_MAP.put(payCodeAnn.value(), (IPay)v);
            });
        }
    }
}
@RestController
public class PayController {
    
    
    
    @GetMapping("/alipay")
    public String aliPay(String type) {
    
    
        IPay pay = PayFactory.getInstance(type);
        return pay.pay();
    }
}

猜你喜欢

转载自blog.csdn.net/qq_45297578/article/details/128664156