• 小谈设计模式(3)—策略模式


    专栏介绍

    专栏地址

    link

    专栏介绍

    主要对目前市面上常见的23种设计模式进行逐一分析和总结,希望有兴趣的小伙伴们可以看一下,会持续更新的。希望各位可以监督我,我们一起学习进步,加油,各位。
    在这里插入图片描述

    策略模式

    策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列的算法,将每个算法封装起来,使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户端。

    主要角色

    当我们使用策略模式时,通常会涉及三个主要角色:环境(Context)、抽象策略(Strategy)和具体策略(Concrete Strategy)。

    环境(Context)

    环境类是策略模式的核心,它持有一个策略对象的引用,并在运行时根据具体需求调用策略对象的算法。环境类提供了一个接口或方法,用于设置和获取策略对象。在客户端使用策略模式时,通常需要与环境类进行交互。

    抽象策略(Strategy)

    抽象策略类是策略模式的接口或抽象类,定义了具体策略类所必须实现的算法。抽象策略类通常包含一个或多个抽象方法,用于描述策略的行为。客户端通过调用抽象策略类中的方法来使用具体策略。

    具体策略(Concrete Strategy)

    具体策略类是策略模式的实现类,实现了抽象策略类中定义的算法。具体策略类根据具体的业务需求,实现了不同的算法逻辑。在客户端使用策略模式时,可以根据需要选择合适的具体策略类。

    角色总结

    环境类持有一个策略对象的引用,并在运行时根据具体需求调用策略对象的算法。抽象策略类定义了具体策略类所必须实现的算法,而具体策略类实现了具体的算法逻辑。通过使用策略模式,可以将算法的定义和使用分离,提高代码的灵活性、可维护性和可扩展性。
    在这里插入图片描述

    核心思想

    策略模式的核心思想是将算法的定义和使用分离。在策略模式中,我们将不同的算法封装成不同的策略类,并通过环境类持有一个策略对象的引用。在运行时,根据具体需求选择合适的策略对象,并调用其算法。

    封装算法

    策略模式将不同的算法封装成不同的策略类。每个策略类都实现了一种具体的算法逻辑。通过封装算法,我们可以将其与其他代码分离,使得算法的定义更加清晰、可读、可维护。

    在这里插入图片描述

    定义抽象策略

    策略模式定义了一个抽象策略类,其中包含了策略类所必须实现的方法。抽象策略类可以是一个接口或者抽象类。通过定义抽象策略,我们可以统一不同策略类的接口,使得客户端可以以统一的方式使用不同的策略。

    使用环境类

    策略模式通过环境类持有一个策略对象的引用。在运行时,客户端可以根据具体需求选择合适的策略对象,并将其设置到环境类中。环境类在运行时根据具体需求调用策略对象的算法,实现了算法的动态切换。

    思想总结

    通过将算法的定义和使用分离,策略模式提高了代码的灵活性、可维护性和可扩展性。它使得算法的修改和增加变得更加简单,不需要修改原有的代码。同时,策略模式也符合开闭原则,可以方便地增加新的策略类。
    在这里插入图片描述

    Java代码实现——以一个游戏角色攻击方式的例子

    首先,我们定义一个抽象策略类 AttackStrategy,它声明了一个 attack() 方法:

    public interface AttackStrategy {
        void attack();
    }
    
    • 1
    • 2
    • 3

    然后,我们定义两种具体的攻击策略类:MeleeAttackStrategy 和 RangedAttackStrategy,它们分别实现了 AttackStrategy 接口:

    public class MeleeAttackStrategy implements AttackStrategy {
        @Override
        public void attack() {
            System.out.println("近战攻击");
        }
    }
    
    public class RangedAttackStrategy implements AttackStrategy {
        @Override
        public void attack() {
            System.out.println("远程攻击");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    接下来,我们定义一个环境类 Character,它持有一个 AttackStrategy 对象,并提供一个 setAttackStrategy() 方法用于动态设置攻击策略:

    public class Character {
        private AttackStrategy attackStrategy;
    
        public void setAttackStrategy(AttackStrategy attackStrategy) {
            this.attackStrategy = attackStrategy;
        }
    
        public void attack() {
            attackStrategy.attack();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    最后,我们可以在客户端中使用策略模式:

    
    public class Client {
        public static void main(String[] args) {
            Character character = new Character();
            
            character.setAttackStrategy(new MeleeAttackStrategy());
            character.attack(); // 输出:近战攻击
            
            character.setAttackStrategy(new RangedAttackStrategy());
            character.attack(); // 输出:远程攻击
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    代码分析

    在上述代码中,我们通过设置不同的攻击策略,使得角色可以使用不同的攻击方式。这样,当需要增加新的攻击方式时,只需要实现新的具体策略类,并在客户端中设置新的攻击策略即可,而不需要修改原有的代码。

    优缺点分析

    优点

    算法的封装性

    策略模式将不同的算法封装成不同的策略类,使得每个策略类都只关注自己的算法逻辑,提高了代码的可读性和可维护性。

    策略的替换性

    由于策略模式将算法的定义和使用分离,所以在运行时可以根据具体需求选择不同的策略对象,实现算法的动态切换。这样可以方便地替换和扩展算法,而不需要修改原有的代码。

    算法的扩展性

    策略模式符合开闭原则,可以方便地增加新的策略类。当需要增加新的算法时,只需要添加一个新的策略类,并在环境类中设置该策略对象即可,不需要修改原有的代码。

    算法的复用性

    策略模式将算法封装成独立的策略类,可以在不同的场景中复用相同的算法。这样可以避免代码的重复编写,提高了代码的复用性。

    在这里插入图片描述

    缺点

    增加了类的数量

    使用策略模式会增加类的数量,每个具体策略类都需要单独定义一个类。如果策略较多,可能会导致类的数量过多,增加代码的复杂性。

    客户端需要了解不同的策略类

    客户端在使用策略模式时,需要了解不同的策略类,并选择合适的策略对象。如果策略较多,可能会增加客户端的复杂性。

    策略的选择逻辑

    在使用策略模式时,需要根据具体需求选择合适的策略对象。这个选择逻辑可能会比较复杂,需要考虑多个因素,增加了代码的复杂性。

    优缺点总结

    总的来说,策略模式通过将算法的定义和使用分离,提高了代码的灵活性、可维护性和可扩展性。它将不同的算法封装成不同的策略类,实现了算法的动态切换和复用。然而,策略模式也会增加类的数量,增加客户端的复杂性,并且需要考虑策略的选择逻辑。在使用策略模式时,需要权衡其优点和缺点,选择合适的使用方式。

  • 相关阅读:
    ThePASS 研究院|探索 Aragon:开创性的 DAO 基础设施实现全面治理
    04_数据库
    【前端验证】通关寄存器与ral_model —— 在uvm验证平台中连接ral_model并发起读写操作
    解决Unity-2020 安卓异形屏黑边
    Cenots7 离线安装部署PostgreSQL
    python+vue+elementui花卉种植技术网站
    腾讯C++二面,全程2小时追问基础!
    conda安装与镜像源配置
    【数据库原理及应用教程】第三章 SQL
    福利又来了,mongo还不会快来练起来!操作汇总
  • 原文地址:https://blog.csdn.net/weixin_74888502/article/details/132940630