• 小侃设计模式(十三)-策略模式


    1.概述

    策略模式(Strategy Pattern)是一种比较简单的模式,它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。策略模式具有较强的实用性,当一个对象拥有很多行为,且这些行为大部分很类似,需要大量的if…else来进行区分,使用策略模式能够有效降低耦合,降低代码复杂度。本文将分析策略模式的原理及使用方式。

    2.原理及使用

    2.1 原理

    策略模式的类图如下:
    在这里插入图片描述

    策略模式主要包含三个角色:

    Strategy(抽象策略角色):定义所有支持的算法的公共接口,通常是接口;
    StrategyA、StrategyB(具体策略角色):实现抽象策略中的操作,该类含有具体的算法;
    Context(封装角色):它封装了高层模块对策略、算法的直接访问,封装了可能存在的变化,起承上启下的作用。

    2.2 案例

    鸡分为野鸡、圈养的鸡,不同的鸡有不同的行为,比如飞翔和叫,野鸡和圈养的鸡各不相同,圈养的鸡不会飞翔。传统的方式是定义一个基类Chicken,野鸡和家鸡分别继承Chicken,实现自己的方法。这其实是有问题的,明明家鸡不会飞,却要继承飞的方法,拥有这个行为。
    如果用策略模式实现上述案例,如下:
    在这里插入图片描述
    代码如下:

    public class Chicken {
    
        public FlyBehavior flyBehavior;
    
        public Chicken(FlyBehavior flyBehavior) {
            this.flyBehavior = flyBehavior;
        }
    
        /**
         * 类型
         */
        private String type;
    
        /**
         * 颜色
         */
        private String color;
    
        /**
         * 图片
         */
        private String image;
    
        /**
         * 年龄
         */
        private Integer age;
    
    
        public void eat() {
            System.out.println("鸡都吃五谷杂粮");
        }
    
        public void method() {
            flyBehavior.fly();
        }
    }
    
    public class Pheasant extends Chicken{
    
        public Pheasant(FlyBehavior flyBehavior) {
            super(flyBehavior);
        }
    
        public void method() {
            System.out.println("这是野鸡");
            flyBehavior.fly();
        }
    }
    
    public class HomeChicken extends Chicken {
    
        public HomeChicken(FlyBehavior flyBehavior) {
            super(flyBehavior);
        }
    
        public void method() {
            System.out.println("这是家养的鸡");
            flyBehavior.fly();
        }
    
    }
    
    public interface FlyBehavior {
    
        void fly();
    }
    
    public class FlyHigh implements FlyBehavior {
    
        @Override
        public void fly() {
            System.out.println("飞的又高又远!");
        }
    }
    
    public class CanNotFly implements FlyBehavior {
    
        @Override
        public void fly() {
            System.out.println("可惜这只鸡不会飞");
        }
    
    }
    
    public class Test {
        public static void main(String[] args) {
            FlyHigh flyHigh = new FlyHigh();
            CanNotFly canNotFly = new CanNotFly();
    
            HomeChicken homeChicken = new HomeChicken(canNotFly);
            homeChicken.method();
    
            System.out.println("------------------------");
    
            Pheasant pheasant = new Pheasant(flyHigh);
            pheasant.method();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99

    测试结果如下:
    在这里插入图片描述

    2.3 策略模式的优缺点

    2.3.1 优点

    1.扩展性良好,新增算法时,只需新增一个策略类即可,其它无需修改;
    2.算法切换灵活:不同的策略类在使用时传入到封装角色中,可以灵活切换;
    3.避免使用多重条件判断:使用策略模式能够有效减少代码中的if…else判断语句,增强程序可读性。

    2.3.2 缺点

    1.容易造成类爆炸:当策略过多时,策略类会有很多,不易复用;
    2.所有的策略类都要对外暴露,违反迪米特法则。

    3.小结

    1.策略模式的关键是:分析项目中变化部分与不变部分,它的核心思想是:多用组合/聚合少用继承;用行为类组合,而不是行为的继承;
    2.体现了“对修改关闭,对扩展开放”原则,客户端增加行为不用修改原有代码,只要添加一种策略(或者行为)即可,避免了使用多重转移语句(if…else if…else);
    3.提供了可以替换继承关系的办法:策略模式将算法封装在独立的Strategy类中使得你可以独立于其Context改变它,使它易于切换、易于理解、易于扩展;
    4.需要注意的是:每添加一个策略就要增加一个类,当策略过多是会导致类数目庞大。

    4.参考文献

    1.《设计模式之禅》-秦小波著
    2.《大话设计模式》-程杰著
    3.https://www.bilibili.com/video/BV1G4411c7N4-尚硅谷设计模式

  • 相关阅读:
    Java面向对象详解(上)
    Java - AQS-CountDownLatch实现类(二)
    Pytorch常用的4种随机数生成方法
    android 内存管理
    java酒店预订网站设计与实现
    电脑重装系统如何在 Win11查看显卡型号信息
    ESP8266-Arduino编程实例-MLX90615红外测温仪驱动
    【EI会议征稿】JPCS独立出版-第五届新材料与清洁能源国际学术会议(ICAMCE 2024)
    河北安新复合型水稻 国稻种芯·中国水稻节:雄安生态示范区
    解析java中的缓冲字符输入流
  • 原文地址:https://blog.csdn.net/qq_33479841/article/details/127985324