zoukankan      html  css  js  c++  java
  • 设计模式之策略模式(一)

    第一、什么是策略模式

    策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理,最终可以实现解决多重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("
    " +
                "SELECT  id as id ,CHANNEL_NAME as CHANNELNAME ,CHANNEL_ID as CHANNELID,strategy_bean_id AS strategybeanid
    " +
                "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');

  • 相关阅读:
    数据可视化之 图表篇(七)柱形图
    数据可视化之 图表篇(六)桑基图
    数据可视化之 图表篇(五) PowerBI图表不够炫酷?来看看这个
    数据可视化之 图表篇(四) 那些精美的Power BI可视化图表
    数据可视化之 图表篇(三)体验Power BI最新发布的AI图表:分解树
    数据可视化之 图表篇(二)如何用Power BI制作疫情地图?
    数据可视化之 图表篇(一)Power BI可视化,几张图表认识疫情现状
    MCMC随机采样
    Linux中的计划作业
    Linux进程
  • 原文地址:https://www.cnblogs.com/cxyyh/p/10828994.html
Copyright © 2011-2022 走看看