Spring结合策略模式和工厂模式干掉if-else

1.jpeg

前言

无意中在掘金上看到cipher的文章《Spring Boot中如何干掉if else》后受到启发,可以利用策略模式简化过多的if else代码,但我觉得在Spring框架中的结合策略模式和工厂模式可以更加简化if-else。

生活中常见比如某外卖平台,有多种支付方式:支付宝、微信、银行卡等.

我们可以看看传统实现方式:

伪代码:

public class Cashier {

    public Cashier(Pay pay){
        pay = pay;
    }

    public String pay(OrderDTO dto) {
        String type = dto.getType();
        if ("alipay".equals(type)) {
            //alipay()方法
        } else if ("wepay".equals(type)) {
            //wepay()方法
        } else if ("bankpay".equals(type)) {
            //bankpay()方法
        }
    }
}


/**
 * 支付宝支付
 */
public class AlipayServiceImpl implements PayService {

    @Override
    public void alipay() {
         system.out.println("支付宝支付");
    }
}


/**
 * 微信支付
 */
public class WepayServiceImpl implements PayService {

    @Override
    public void wepay() {
         system.out.println("微信支付");
    }
}


/**
 * 银行卡支付
 */
public class BankpayServiceImpl implements PayService {

    @Override
    public void bankpay() {
         system.out.println("银行卡支付");
    }
}


/**
 * 支付接口
 */
public interface PayService {
    alipay();
    wepay();
    bankpay();
}

下面来看看结合策略模式工厂模式的实现方式:

首先定义一个支付类工厂:

@Component
public class PayFactory implements InitializingBean {
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private OrderDTO dto;

    private Map<String, PayService> payMap = new HashMap<>();

    public boolean registry(String key, PayService pay) {
        if (payMap.containsKey(key)) {
            return false;
        }
        payMap.put(key, pay);
        return true;
    }

    public PayService get() {
        String type = OrderDTO.getValue("pay_type");
        if (StringUtils.isBlank(type)) {
            type = "请先选择一种支付方式!";
        }
        return payMap.get(type);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        payMap.put("alipay", applicationContext.getBean(AlipayServiceImpl.class));
        payMap.put("wepay", applicationContext.getBean(WepayServiceImpl.class));
        payMap.put("bankpay", applicationContext.getBean(BankpayServiceImpl.class));
    }
}


public class Cashier {

    @Autowired
    protected PayFactory payFactory;
    @Autowired
    private OrderDTO dto;
    
    payFactory.get().alipay();
}

这样,在Spring初始化的时候,当创建AlipayService、WepayService和BankpayService的时候,会在Bean的属性初始化之后,把这个Bean注册到PayFactory中。以上代码,其实还是有一些重复代码的,这里面还可以引入模板方法模式进一步精简,这里我就不展开了。

总结

策略模式可以充分的体现面向对象设计原则多用组合,少用继承、针对接口编程,不针对实现编程两个设计原则。

通过策略模式、工厂模式以及Spring的InitializingBean,提升了代码的可读性以及可维护性,彻底消灭了一坨if-else。这种做法,大家可以立刻尝试起来,这种实践,是我们日常开发中经常用到的,而且还有很多衍生的用法,也都非常好用。有机会后面再介绍

策略模式的优缺点

优点:

  • 策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。

  • 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。

  • 使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承的办法还要原始和落后。

缺点:

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。这种策略类的创建及选择其实也可以通过工厂模式来辅助进行。

  • 由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很可观。可以通过使用享元模式在一定程度上减少对象的数量。

参考文章:

漫话:如何给女朋友解释什么是策略模式?

业务复杂=if else?刚来的大神竟然用策略+工厂彻底干掉了他们!


已有 0 条评论

    感谢参与互动!