zoukankan      html  css  js  c++  java
  • 设计模式-策略模式学习笔记

    前言:策略模式是和简单工厂一起在几天前学的,今晚有空正好写下来

    策略模式

    策略模式是定义一组算法,将每一种算法都封装成共同接口的独立类中,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。


    • 优缺点

    优点:

    1. 满足开放-封闭原则(扩展算法时,直接新增算法类,不用修改上下文)
    2. 降低了策略和策略调用者的耦合度
    3. 一个算法发生修改时,其他算法可以不用暴露
    4. 简化了算法的单元测试

    缺点:

    1. 每个算法独立成类,算法越多,类越来越多
    2. 所有的策略类都用暴露出去,客户端必须要知道所有的策略类

    • 结构

    Strategy:抽象的策略(一个借口或抽象类)

    ConcreteStrategy:具体的策略(实现了Strategy的算法类)

    Context:策略上下文(策略模式的上下文类,持有Strategy类的引用,也可将策略的参数放置在上下文类中)


    • 代码

    引用《大话设计模式》中的例子,商场购物有优惠,现有优惠方案:1、打折  2、满减,可能会有优惠方案:1、赠送积分

            抽出父类策略类。

    /**
     * @ Author     :fonxi
     * @ Date       :2019/5/10 2:56
     * @ Description:策略类
     */
    public interface Super {
        Double count(Context ctx);
    }
    

      然后将每一种优惠方案当做一种算法,独立封装成具体策略类。

    /**
     * @ Author     :fonxi
     * @ Date       :2019/5/10 2:56
     * @ Description:具体策略-折扣类
     */
    public class Discount implements Super{
        @Override
        public Double count(Context ctx) {
            return ctx.getDiscountRate()*ctx.getMoney();
        }
    }
    

      

    /**
     * @ Author     :fonxi
     * @ Date       :2019/5/10 2:56
     * @ Description:具体策略-返利类
     */
    public class Rebate implements Super{
    
        @Override
        public Double count(Context ctx) {
            if(ctx.getMoney()>ctx.getRebateMoeny()){
                return ctx.getMoney() - Math.floor(ctx.getMoney()/ctx.getRebateMoeny()) * ctx.getRebateValue();
            }
            return ctx.getMoney();
        }
    }
    

      上下文中放置具体算法所需的参数,持有策略类的引用,并返回具体调用的策略算法。

    /**
     * @ Author     :fonxi
     * @ Date       :2019/5/10 3:01
     * @ Description:上下文
     */
    @Data
    public class Context {
    //总金额 private Double money; //折扣 private Double discountRate; //到达额度 产生返利 private Double rebateMoeny; //返利值 private Double rebateValue; //持有一个策略对象 private Super superObject; public Context(Double rebateMoeny,Double rebateValue,Double money,Double discountRate,Super superObject){ this.rebateMoeny = rebateMoeny; this.rebateValue = rebateValue; this.money = money; this.discountRate = discountRate; this.superObject = superObject; } public Double getResult(Context ctx){ return superObject.count(ctx); } }

      在客户端,根据需求选择不同的策略,然后通过策略上下文得到不同的策略实现。

    /**
     * @ Author     :fonxi
     * @ Date       :2019/5/10 3:10
     * @ Description:客户端选择类
     */
    public class Calculator {
    
        public void print(){
            Scanner s = new Scanner(System.in);
            Context context = null;
            //折扣
            Double discountRate = null;
            //到达额度 产生返利
            Double rebateMoeny = null;
            //返利值
            Double rebateValue = null;
            try {
                System.out.println("请输入总金额");
                Double money = s.nextDouble();
                System.out.println("请选择折扣方式:1、打折2、返利");
                String type = s.next();
                if(type.equals("1")){
                     System.out.println("请输入折扣");
                     discountRate = s.nextDouble();
                }
                else if(type.equals("2")){
                    System.out.println("请输入满减额度");
                    rebateMoeny = s.nextDouble();
                    System.out.println("请输入满减值");
                    rebateValue = s.nextDouble();
                }
                Super superObject = null;
                switch (type){
                    case "1":
                        superObject = new Discount();
                        break;
                    case "2":
                        superObject = new Rebate();
                        break;
                    default:
                        System.out.println("输入选择有误");
                        break;
                }
                context = new Context(rebateMoeny,rebateValue,money,discountRate,superObject);
                System.out.println("结算金额是:"+context.getResult(context));
            }catch (Exception e){
                System.out.println("请输入有误"+e.getMessage());
            }
        }
    }

    • 总结

    策略模式使得每种算法都能够灵活的替换,并且在新增算法时不修改原有代码,不管是耦合性还是可扩展性都被大大的优化了,不过在客户端调用策略时会出现臃肿的选择,需要通过其他方式去优化。

  • 相关阅读:
    Elixir 简介
    docker 基础
    函数式和面向对象
    react-native 简介及环境
    Ecto 总结
    使用 dep 配置 golang 开发环境
    docker 私有仓库简易搭建
    Elixir 单元测试
    基于资源的权限系统-API设计
    差商代微商的方法求解一阶常微分方程
  • 原文地址:https://www.cnblogs.com/fonxi/p/10851004.html
Copyright © 2011-2022 走看看