使用策略模式解決多重判斷if-else問題


前言

  也許我們的代碼中遇到過多重判斷if-else語句,但是這樣的代碼可讀性差,並且當擴展時,違反了“開閉原則”。阿里開發規范中提到的解決方法有:衛語句,策略模式,狀態模式。本文講述的是通過策略模式來解決多重判斷if-else語句問題。

  github代碼地址:https://github.com/Chenrencun/pay-strategy

正文

  一、多重判斷if-else代碼

  我們通過支付接口的例子來講述。代碼如下:

  1、Controller層

@RestController
public class PayController {

    @Autowired
    private PayService payService;

    @RequestMapping("/pay")
    public String pay(String type, String amount){
        return payService.pay(type, amount);
    }
}

  2、Service層

public interface PayService {

    /**
     * 支付接口
     * @param type 支付類型
     * @param amount 支付金額
     * @return
     */
    String pay(String type, String amount);
}


@Service
public class PayServiceImpl implements PayService{

    private static String MSG = "使用 %s ,消費了 %s 元";

    @Override
    public String pay(String type, String amount) {
        if (PayEnum.ALI_PAY.getType().equals(type)){
            // 支付寶支付
            return String.format(MSG, PayEnum.ALI_PAY.getDescription(), amount);
        } else if (PayEnum.WECHAT_PAY.getType().equals(type)) {
            // 微信支付
            return String.format(MSG, PayEnum.WECHAT_PAY.getDescription(), amount);
        } else if (PayEnum.UNION_PAY.getType().equals(type)) {
            // 銀聯支付
            return String.format(MSG, PayEnum.UNION_PAY.getDescription(), amount);
        }
        return "輸入的支付類型錯誤!";
    }
}

  3、Enum枚舉類

public enum  PayEnum {

    ALI_PAY("ali", "支付寶支付"),
    WECHAT_PAY("wechat", "微信支付"),
    UNION_PAY("union", "銀聯支付");

    private String type;

    private String description;

    PayEnum(String type, String description) {
        this.type = type;
        this.description = description;
    }

    public String getType() {
        return type;
    }

    public String getDescription() {
        return description;
    }
}

  當需要增加一個信用卡支付時,需要修改原來的代碼,這樣就違法了“開閉原則”。

 

  二、策略模式代碼

  主要是Service層代碼有所改變。

  1、Service層

public interface PayService {

    /**
     * 支付接口
     * @param type 支付類型
     * @param amount 支付金額
     * @return
     */
    String pay(String type, String amount);
}


@Service
public class PayServiceImpl implements PayService{

    private static String MSG = "使用 %s ,消費了 %s 元";

    @Override
    public String pay(String type, String amount) {

        PayStrategy payStrategy = PayStrategyFactory.getPayStrategy(type);
        if (payStrategy == null){
            return "輸入的支付類型錯誤!";
        }
        return payStrategy.pay(type, amount);
    }
}

  2、對多重判斷if-else語句的改造

public interface PayStrategy {

    String MSG = "使用 %s ,消費了 %s 元";

    String pay(String type, String amount);
}


@Component("aliPayStrategy")
public class AliPayStrategyImpl implements PayStrategy{

    @Override
    public String pay(String type, String amount) {
        return String.format(MSG, PayEnum.ALI_PAY.getDescription(), amount);
    }
}


@Component("wechatPayStrategy")
public class WechatPayStrategyImpl implements PayStrategy{
    @Override
    public String pay(String type, String amount) {
        return String.format(MSG, PayEnum.WECHAT_PAY.getDescription(), amount);
    }
}


@Component("unionPayStrategy")
public class UnionPayStrategyImpl implements PayStrategy{
    @Override
    public String pay(String type, String amount) {
        return String.format(MSG, PayEnum.UNION_PAY.getDescription(), amount);
    }
}

  3、修改后的枚舉類

public enum  PayEnum {

    ALI_PAY("ali", "支付寶支付", "aliPayStrategy"),
    WECHAT_PAY("wechat", "微信支付", "wechatPayStrategy"),
    UNION_PAY("union", "銀聯支付", "unionPayStrategy");

    private String type;

    private String description;

    private String beanName;

    PayEnum(String type, String description, String beanName) {
        this.type = type;
        this.description = description;
        this.beanName = beanName;
    }

    public String getType() {
        return type;
    }

    public String getDescription() {
        return description;
    }

    public String getBeanName() {
        return beanName;
    }

    public static PayEnum getByType(String type){
        if (type == null){
            return null;
        }
        for (PayEnum payEnum:values()
             ) {
            if (payEnum.getType().equals(type)){
                return payEnum;
            }
        }
        return null;
    }
}

  4、通過以下工具類,能夠獲取到PayStrategy實現類關聯。

public class SpringContextUtil implements ApplicationContextAware {

    /**
     * 上下文對象實例
     */
    private static ApplicationContext applicationContext;

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

    public static ApplicationContext getApplicationContext(){
        return applicationContext;
    }

    public static <T> T getBean(String name){
        return (T)getApplicationContext().getBean(name);
    }

    public static <T> T getBean(String name, Class<T> clazz){
        return getApplicationContext().getBean(name, clazz);
    }


}

  5、Service調用PayStrategy的工廠類,返回PayStrategy的實現類

public class PayStrategyFactory {

    /**
     * 根據type獲取對應PayStrategy實現類
     * @param type
     * @return
     */
    public static PayStrategy getPayStrategy(String type){
        PayEnum payEnum = PayEnum.getByType(type);
        if (payEnum == null){
            return null;
        }
        return SpringContextUtil.getBean(payEnum.getBeanName(), PayStrategy.class);
    }
}

  通過這樣的改造,當我們增加一個信用卡支付時,只需要添加一個PayStrategy的實現類,並在PayEnum枚舉類添加一個信用卡支付的成員就可以了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM