• 设计模式--策略模式



    前言

    需求:
    一天,产品经理走过来对你说。猫啊(自称),帮我设计一个计算器,需要的功能有求最大值,最小值。应不难的吧ㄟ( ▔, ▔ )ㄏ
    本文主要说明设计模式,具体算法实现不在涉及


    一、未使用设计模式

    小小经理,可笑可笑😏,看我一顿操作!

    public class Calculation {
        public static void go(List<Integer> list, String type) throws Exception {
            if (type.equals("1")){
                // 最大值
                System.out.println("最大值");
            }else if (type.equals("2")){
                // 最小值
                System.out.println("最小值");
            }else {
                throw new Exception("error");
            }
        }
    
        public static void main(String[] args) throws Exception {
            List<Integer> list=new ArrayList<>();
            String type="6";
            go(list,type);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    这时,产品经理又来了,瞧我这记性,不止要实现最大最小的计算,还需要有求和,平均值,排序…😵‍💫可能以后给还会在加如更多的算法。

    此时,就可以看出上述设计出现的弊端,在代码中使用了大量的if–else,如果某天经理突然又想出来一些新的需求,就不得不对Calculation的代码进行修改,此时我们就违反了设计原则中的开闭原则,同时也会造成大量的代码在一个类中,难以阅读。我们的目标应该是允许类容易扩展,在不修改现有代码的情况下就可以增加新的行为。

    开闭原则
    类应该对扩展开放,对修改关闭


    二、策略模式

    1.定义

    该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

    2.结构

    1、抽象策略角色(Strategy):通常有一个接口或一个抽象类实现

    2、具体策略角色(ConcreteStrategy):包装了相关的算法和行为

    3、环境角色(Context):持有一个策略类的应用,最终供客户端调用

    在这里插入图片描述

    我们将计算方法抽象为一个策略接口

    public interface NumberGather {
        //调用集合方法的抽象方法
        public void calculation(List<Integer> list);
    }
    
    • 1
    • 2
    • 3
    • 4

    现在只需要为不同的算法建立对应的策略实现类

    最小值:

    public class Min implements NumberGather {
        @Override
        public void calculation(List<Integer> list) {
            List<Integer> list1 = new ArrayList<Integer>();
            Integer min = Collections.min(list1);
            System.out.println("最小值为"+min);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    最大值:

    public class Max implements NumberGather{
        @Override
        public void calculation(List<Integer> list) {
            List<Integer> list1 = new ArrayList<Integer>();
            Integer max = Collections.max(list1);
            System.out.println("最大值为"+max);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    平均值:

    public class Average implements NumberGather {
        @Override
        public void calculation(List<Integer> list) {
            List<Integer> list1 = new ArrayList<Integer>();
            double sum =list1.stream().mapToDouble(Integer::doubleValue).sum();
            int size = list1.size();
            double avg = sum/size;
            System.out.println("平均值为"+avg);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    环境类:

    public class Context {
        private NumberGather numberGather;
        public Context(NumberGather numberGather){
            this.numberGather=numberGather;
        }
        public void go(List<Integer> list){
            numberGather.calculation(list);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    test:

    public class Demo {
        public static void main(String[] args) {
            List<Integer> list1 = new ArrayList<Integer>();
            list1.add(8);
            list1.add(7);
            list1.add(16);
            list1.add(12);
            list1.add(3);
            Context context=new Context(new Max());
            context.go(list1);
    
            Context context1=new Context(new Average());
            context1.go(list1);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    三、应用场景

    1、 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。
    2、 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。
    3、 对客户隐藏具体策略(算法)的实现细节,彼此完全独立。

    四、优缺点

    • 策略类之间可以自由切换。由于策略类都实现同一个接口,所以使它们之间可以自由切换。
      易于扩展。
    • 增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码。符合开闭原则
    • 避免使用多重条件选择语句,充分体现面向对象设计思想。

    • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这点可以考虑使用IOC容器和依赖注入的方式来解决
    • 策略模式会造成很多的策略类,可能造成类爆炸。

    参考资料

    百度

    https://juejin.cn/post/7006126086715113480

  • 相关阅读:
    python pytorch- TextCNN TextRNN FastText Transfermer (中英文)文本情感分类实战(附数据集,代码皆可运行)
    VUE必知必会
    密钥密码学(三)
    043—pandas 分组运用聚合函数agg制作汇总表
    图形学 - 纹理的应用
    【云原生 | Kubernetes篇】自建高可用k8s集群优化
    第一百六十回 SliverPadding组件
    RDB与AOF
    动静态库的制作
    Mysql(基本介绍+下载安装+服务器+基本使用+建库建表+navicat/mybitas工具+外键及实例)
  • 原文地址:https://blog.csdn.net/weixin_63802890/article/details/128188839