使用 策略模式 解決if判斷問題

1.現在有一個需求,根據不同的傳參payCode選擇不同的支付模式 ,

常見的if判斷如下

public String toPayHtml(String payCode){
        if("ALI_PAY".equals(payCode)){
            return "使用支付寶支付....";
        }else if ("WEIXIN_PAY".equals(payCode)){
            return "使用微信支付....";
        }else if ("XIAOMI".equals(payCode)){
            return "使用小米支付....";
        }
        return null;
}

策略模式實現1  

源碼鏈接:https://pan.baidu.com/s/1-RwF4IIKNMzDww4UIJIjkA      提取碼:adua

1.定義接口, 定義共同行爲方法

public interface PayStrategy {

    //共同方法行爲
    String toPayHtml();
}

2.分別定義實現類,支付寶支付,微信支付,小米支付

public class AliPayStrategy implements PayStrategy {

    @Override
    public String toPayHtml() {
        return "調用支付寶接口.....";
    }
}
public class WeiXinPayStrategy implements PayStrategy {

    @Override
    public String toPayHtml() {
        return "調用微信支付....";
    }
}
public class XiaoMiPayStrategy implements PayStrategy {
    @Override
    public String toPayHtml() {
        return "調用小米支付....";
    }
}

3.定義枚舉類型,存放所有策略的實現

//策略枚舉類,存放所有策略的實現
public enum PayEnumStrategy {
    
    //支付寶支付
    ALI_PAY("com.zhang.strategy.impl.AliPayStrategy"),
    
    //小米支付
    XIAOMI_PAY("com.zhang.strategy.impl.XiaoMiPayStrategy"),
    
    //微信支付
    WECHAT_PAY("com.zhang.strategy.impl.WeiXinPayStrategy");
    
    PayEnumStrategy(String className){
        this.setClassName(className);
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }
    
    //class完整地址
    private String className;
}

4.使用工廠初始化實現策略ben,獲取具體策略實現

public class StrategyFactory {

    //使用策略工廠獲取具體策略實現
    public static PayStrategy getPayStrategy(String stratrgyType){
        try {
            //獲取具體的策略class地址
            String className = PayEnumStrategy.valueOf(stratrgyType).getClassName();
            return  (PayStrategy)Class.forName(className).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

5.定義上下文,獲取具體實現策略,並執行對應策略

@Component
public class PayContextStrategy {

    public String toPayHtml(String payCode){
        if(StringUtils.isEmpty(payCode)){
            return "payCode不能爲空!...";
        }
        PayStrategy payStrategy = StrategyFactory.getPayStrategy(payCode);
        if(payStrategy==null){
            return "沒有找到具體策略的實現";
        }
        return payStrategy.toPayHtml();
    }
}

6.測試

@RestController
public class PayControlller {

    @Autowired
    private PayContextStrategy payContextStrategy;

    @GetMapping("/toPayHtml")
    public String toPayHtml(String payCode){
        return payContextStrategy.toPayHtml(payCode);
    }
}

策略模式實現2 -通過數據庫管理更優

源碼鏈接:https://pan.baidu.com/s/1M7UM-TW3BDgaJ0EXKtrjCw 
提取碼:fhvb

1.定義接口, 定義共同行爲方法

public interface PayStrategy {

    //共同方法行爲
    String toPayHtml();
}

2.分別定義實現類,支付寶支付,微信支付,小米支付,並注入到Spring容器

@Component
public class AliPayStrategy implements PayStrategy {

    @Override
    public String toPayHtml() {
        return "調用支付寶接口.....";
    }
}
@Component
public class WeiXinPayStrategy implements PayStrategy {

    @Override
    public String toPayHtml() {
        return "調用微信支付....";
    }
}
@Component
public class XiaoMiPayStrategy implements PayStrategy {
    @Override
    public String toPayHtml() {
        return "調用小米支付....";
    }
}

3.數據庫存儲所有策略實現,後期可配置控制是否開啓處理

CREATE TABLE `strategy` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵id',
  `change_name` varchar(50) DEFAULT NULL COMMENT '名稱',
  `change_id` varchar(50) DEFAULT NULL COMMENT 'key_id',
  `change_ben_name` varchar(255) DEFAULT NULL COMMENT '實現類名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

4.編輯策略上下文,獲取具體策略

@Component
public class PayContextStrategy {

    @Autowired
    private PayStrategyMapper getPayStrategyMapper;

    public String toPayHtml(String payCode){
        if(StringUtils.isEmpty(payCode)){
            return "payCode不能爲空!...";
        }
        //查詢數據庫獲取pay策略實體
        PayStrategyEntity payStrategyEntity = getPayStrategyMapper.getStrategyEntity(payCode);
        if(payStrategyEntity==null){
            return "數據庫沒有找到具體策略的實現";
        }
        //獲取執行策略的類名-首字母小寫
        String changeBenName = payStrategyEntity.getChangeBenName();
        if(StringUtils.isEmpty(changeBenName)){
            return "沒有找到具體策略的實現";
        }
        //通過spring找到策略ben對象
        PayStrategy payStrategy = SpringUtils.getBean(changeBenName, PayStrategy.class);
        //執行策略
        return payStrategy.toPayHtml();
    }
}

5.Spring上下文獲取Spring注入ben對象工具類

//spring上下文中獲取ben對象
@Component
public class SpringUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

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

    //獲取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    //通過name獲取 Bean.
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    //通過class獲取Bean.
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    //通過name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}

6.實體 和 mapper就不貼了 ,測試

@RestController
public class PayControlller {

    @Autowired
    private PayContextStrategy payContextStrategy;

    @GetMapping("/toPayHtml")
    public String toPayHtml(String payCode){
        return payContextStrategy.toPayHtml(payCode);
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章