設計模式之策略模式(一)


第一、什么是策略模式

策略模式是對算法的包裝,是把使用算法的責任和算法本身分割開來,委派給不同的對象管理,最終可以實現解決多重if判斷問題。

1.環境(Context)角色:持有一個Strategy的引用。

2.抽象策略(Strategy)角色:這是一個抽象角色,通常由一個接口或抽象類實現。此角色給出所有的具體策略類所需的接口。

3.具體策略(ConcreteStrategy)角色:包裝了相關的算法或行為。

第二、策略模式應用場景

比如搭建聚合支付平台的時候,這時候需要對接很多第三方支付接口,比如支付寶、微信支付、小米支付等。

通過傳統if代碼判斷的,后期的維護性非常差!

public String toPayHtml2(String payCode){ if(payCode.equals("ali_pay")){ return  "調用支付寶接口..."; } if(payCode.equals("xiaomi_pay")){ return  "調用小米支付接口"; } if(payCode.equals("yinlian_pay")){ return  "調用銀聯支付接口..."; } return  "未找到該接口..."; }

這時候可以通過策略模式解決多重if判斷問題。

第三、策略模式架構圖

第四、策略模式案例

1、引入maven依賴

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.6.RELEASE</version>
    </parent>
    <dependencies>
        <!-- sprinboot web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!-- mysql 依賴 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>

 2、創建一個接口PayStrategy(抽象角色)

/** * 抽象角色 * 策略類 */
public interface PayStrategy { /** * 共同算法實現骨架 * @return
     */
    public String toPayHtml(); }

 3、創建具體實現類(AliPayStrategy)

/** * 支付子類 */ @Component public class AliPayStrategy implements PayStrategy { @Override public String toPayHtml() { return "調用支付接口"; } }

4、創建具體實現類(XiaoMiPayStrategy)

/** * 小米實現類 */ @Component public class XiaoMiPayStrategy implements PayStrategy { @Override public String toPayHtml() { return "調用小米接口"; } }

 5、創建一個得到bean對象的工具類(SpringContextUtil)

/** * 得到bean對象 * */ @Component public class SpringContextUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; /** * 實現ApplicationContextAware接口的回調方法。設置上下文環境 * * @param applicationContext */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } //獲取applicationContext
    public static ApplicationContext getApplicationContext() { return applicationContext; } //通過name獲取 Bean.
    public static Object getBean(String name){ return getApplicationContext().getBean(name); } //通過class獲取Bean.
    public  <T> T getBean(Class<T> clazz){ return getApplicationContext().getBean(clazz); } //通過name,以及Clazz返回指定的Bean
    public  <T> T getBean(String name,Class<T> clazz){ return getApplicationContext().getBean(name, clazz); } }

6、創建一個實體類

@Data public class PaymentChannelEntity { /** ID */
    private Integer id; /** 渠道名稱 */
    private String channelName; /** 渠道ID */
    private String channelId; /** * 策略執行beanId */
    private String strategyBeanId; }

 7、創建一個mapper接口

public interface PaymentChannelMapper { @Select("\n" +
            "SELECT  id as id ,CHANNEL_NAME as CHANNELNAME ,CHANNEL_ID as CHANNELID,strategy_bean_id AS strategybeanid\n" +
            "FROM payment_channel where CHANNEL_ID=#{payCode}") public PaymentChannelEntity getPaymentChannel(String payCode); }

 8、創建一個上下文對象獲取對應的實現類

/** * 上下文 */ @Component public class PayContextService { @Autowired private PaymentChannelMapper paymentChannelMapper; @Autowired private SpringContextUtil springContextUtil; public String toPayHtml(String payCode){ //驗證參數
        if(StringUtils.isBlank(payCode)){ return "參數不能為空"; } //使用該paycode查詢
        PaymentChannelEntity paymentChannel = paymentChannelMapper.getPaymentChannel(payCode); if(paymentChannel==null){ return  "該渠道為空..."; } //獲取對應的beanid
        String strategyBeanId = paymentChannel.getStrategyBeanId(); if (strategyBeanId==null){ return "beanId為空"; } //得到對應的bean
        PayStrategy payStrategy = springContextUtil.getBean(strategyBeanId, PayStrategy.class); // 5.執行具體策略算法
        return payStrategy.toPayHtml(); } }

 9、創建一個controller層

@RestController public class PayController { @Autowired private PayContextService payContextService; @RequestMapping("/index") public String index(String payCode){ return payContextService.toPayHtml(payCode); } }

 10、創建一個啟動類

@SpringBootApplication @MapperScan("com.yehui.mapper") public class StartMainApp { public static void main(String[] args) { SpringApplication.run(StartMainApp.class); } }

11、yml文件

spring: datasource: driver-class-name: com.mysql.jdbc.Driver password: root url: jdbc:mysql://localhost:3306/study
 username: root logging: level: com.yehui.mapper: debug

 啟動測試:

訪問小米: http://localhost:8080/index?payCode=xiaomi_pay

效果

 

訪問支付: http://localhost:8080/index?payCode=ali_pay

效果

 

 12、相關sql

DROP TABLE IF EXISTS `payment_channel`; CREATE TABLE `payment_channel` ( `ID` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', `CHANNEL_NAME` varchar(32) NOT NULL COMMENT '渠道名稱', `CHANNEL_ID` varchar(32) NOT NULL COMMENT '渠道ID', `strategy_bean_id` varchar(255) DEFAULT NULL COMMENT '策略執行beanid', PRIMARY KEY (`ID`,`CHANNEL_ID`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='支付渠道 ';

INSERT INTO `payment_channel` VALUES ('4', '支付寶渠道', 'ali_pay', 'aliPayStrategy');

INSERT INTO `payment_channel` VALUES ('5', '小米支付渠道', 'xiaomi_pay', 'xiaoMiPayStrategy');

 


免責聲明!

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



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