美文网首页
Java 策略模式

Java 策略模式

作者: 索性流年 | 来源:发表于2021-02-09 09:19 被阅读0次

    文集地址

    一句话总结策略模式

    • 主要是一对多,要是一个API需要多种实现方法,便用策略模式

    什么是策略模式?

    • 策略模式就是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理,最终可以实现解决多if重判断问题。

    实现过程

    • 定义策略接口->实现不同的策略类->利用多态或其他方式调用策略. .
      1.环境(Context)角色:持有一个Strategy的引用。。
      2.抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此
      出所有的具体策略类所需的接口。。
      3.具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。。

    优点

    • 维护性增强,扩展性增强,提高可读性。

    缺点

    • 后期维护不通的策略类非常多、代码量增大

    总结

    • 优点大于缺点。

    案例聚合支付

    前提

    • 如若正常聚合支付,一个接口方法中会有多重判断,调用支付宝,调用微信,调用银联。。。。
      如若想要扩展内容首先就要更改这些判断,而这里面的每一个方法都有大量逻辑,一不小心就会牵一发而动全身,而使用策略模式的目的就是增强接口扩展性

    • 定义支付算法共同骨架,PayStrategy

    /*
    * 共同算法定义骨架
    *
    * */
    public interface PayStrategy {
        /*共同算法骨架*/
        public String toPayhtml();
    }
    
    
    • 定义对应实现类这里只是简单模拟返回
    /*阿里支付算法*/
    @Component
    public class AliPayStrategy implements PayStrategy {
        @Override
        public String toPayhtml() {
            return "调用支付宝支付方法";
        }
    }
    
    /*银联支付算法*/
    @Component
    public class YinLianPayStrategy implements PayStrategy {
        @Override
        public String toPayhtml() {
            return "调用银联支付方式";
        }
    }
    
    
    • 新建数据库用于存储支付方式以及对应实现类,创建Dao层获取数据这里是用Mybatis实现Dao层
    @Component
    @Mapper
    public interface PaymentChannelMapper {
    
        @Select("SELECT * FROM payment_channel AS pay WHERE pay.payId = #{payCode}")
        PaymentChannelEntity getPaymentChannel(String payCode);
    }
    
    //实体类
    public class PaymentChannelEntity {
        private String id;
        private String payId;
        private String payType;
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getPayId() {
            return payId;
        }
    
        public void setPayId(String payId) {
            this.payId = payId;
        }
    
        public String getPayType() {
            return payType;
        }
    
        public void setPayType(String payType) {
            this.payType = payType;
        }
    }
    
    
    • 获取SpringIOC容器工具类
    /*使用Bend对象获取Spring容器中对应的类*/
    @Component
    public class SpringUtils implements ApplicationContextAware {
        private static ApplicationContext context;
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            context = applicationContext;
        }
        /*获取context上下文*/
        public static ApplicationContext getApplicationContext(){
            return context;
        }
    
        /*通过name获取Bean*/
        public static Object getBean(String name){
            return getApplicationContext().getBean(name);
        }
    
        /*通过类名获取Bean*/
        public static <T>T getBean(Class<T> className){
            return getApplicationContext().getBean(className);
        }
    
        /*通过name,以及Class返回指定Bean*/
        public static <T>T getBean(String neme, Class<T> className){
            return getApplicationContext().getBean(neme,className);
        }
    }
    
    

    新建.class作用于获取对象实现类

    @Component
    public class PayContextStrategy {
        @Autowired
        public PaymentChannelMapper paymentChannelMapper;
    
        @Autowired
        public SpringUtils springUtils;
    
        public PayContextStrategy() {
            super();
        }
    
        public String toPayHtml(String payCode){
            System.err.println(payCode);
    //        使用PayCode查询数据库获取Bendid
            PaymentChannelEntity paymentChannel = paymentChannelMapper.getPaymentChannel(payCode);
    //        获取bindid,使用spring容器获取实例方法
            if (paymentChannel == null){
                return "没有该渠道信息";
            }
            String strategyBeanId = paymentChannel.getPayType();
            System.err.println(strategyBeanId);
            if (StringUtils.isEmpty(strategyBeanId)){
                return "该渠道配置ben配置";
            }
            PayStrategy payStrategy =  springUtils.getBean(strategyBeanId,PayStrategy.class);
            return payStrategy.toPayhtml();
        };
    }
    

    新建.class 控制器作用于接口测试

    @RestController
    public class PayController {
        @Autowired
        private PayContextStrategy contextStrategy;
    
        @GetMapping("/toPayHtml")
        public String toPayHtml(String payCode){
            if (StringUtils.isEmpty(payCode)){
                return "渠道code不能为空";
            }
            return contextStrategy.toPayHtml(payCode);
        }
    }
    
    

    总结

    • 如若需要接入其他支付方式,则直接创建该支付的实现类存入数据库中,无需改动其他逻辑,这个使用数据库只是例子,可以使用枚举

    案例思路

    • 首先建立支付接口公共骨架,用于后期动态获取实现类→使用数据库存储实现类对象以及类型→查询数据库动态获取实现类→使用Spring获取支付类的具体实现→使用接口调用相关方法测试

    相关文章

      网友评论

          本文标题:Java 策略模式

          本文链接:https://www.haomeiwen.com/subject/acepactx.html