【设计模式-行为型】策略模式

一、什么是策略模式

要说策略模式,那么我脑袋里有一个例子,是一个策略模式使用的大家,那就是在周星驰的电影《国产凌凌漆》中的----达文西。

达文西:"没错就是我,请叫我文西"。

电影中,角色达文西以其机智和创造力,生动地展示了策略模式的精髓。面对电影中的反派角色金枪客的威胁,达文西,这位"聪明的发明家",迅速设计并制造了一种应对紧急情况的策略武器------"要你命3000"。

"要你命3000"是一种超级武器,它巧妙地将西瓜刀、铁链、火药、硫酸、毒药、手枪、手榴弹等十多种武器结合在一起,形成了一种看似强大但实际上荒谬的混合武器。达文西在剧中自豪地介绍他的发明:"要你命三千,西瓜刀,铁链,火药,硫酸,毒药,手枪,手榴弹,杀虫剂,每样都能独当一面,现在集中在一起,看你怕不怕?"这句话不仅展现了达文西的幽默感,也体现了策略模式的核心思想:通过组合不同的元素来应对特定的挑战。

这个场景中的"要你命3000"就是策略模式的一个典型应用。策略模式允许我们在运行时根据不同的情况选择不同的算法或行为,就像达文西根据不同的威胁选择不同的武器一样。这种模式使得系统更加灵活,能够适应不断变化的需求。

策略模式的定义: 策略模式是一种行为设计模式,它定义了一系列算法(要你命3000),将每个算法封装起来(要你命3000中的每个武器),并使它们可以互换(可以使用每种武器应对金枪客)。

二、为什么用策略模式

那么我们可以根据这个示例,来讨论一下为什么要使用策略模式(为啥会想到用要你命3000):

  1. 算法多样性 :在电影中,达文西面对不同的敌人和战斗场景,需要不同的武器。这就像在软件开发中,我们可能需要根据不同的输入或条件来选择不同的算法。策略模式允许我们在运行时选择最合适的算法。例子: 假设我们有一个支付系统,需要支持多种支付方式(现金、信用卡、移动支付等)。每种支付方式都是一个策略。通过策略模式,我们可以轻松地添加新的支付方式,而不需要修改现有的代码。

  2. 代码复用 :达文西的"要你命3000"虽然是一个荒谬的发明,但它展示了如何将不同的工具组合起来以应对特定的挑战。在软件开发中,这意味着我们可以重用已有的算法,而不需要每次都重新编写代码。例子: 在图像处理软件中,我们可能有多种图像滤镜(如模糊、锐化、边缘检测等)。每种滤镜都是一个策略。通过策略模式,我们可以在不同的上下文中重用这些滤镜算法,而不需要为每个新功能重新编写代码。

  3. 简化切换 :在电影中,达文西可能需要快速地从一种武器切换到另一种武器。在软件开发中,策略模式允许我们在运行时轻松地切换算法,而不需要复杂的条件判断。例子: 在游戏开发中,我们可能需要根据玩家的选择或游戏状态来切换不同的AI行为。通过策略模式,我们可以轻松地在不同的AI策略之间切换,以适应游戏的不同阶段或玩家的不同行为。

  4. 提高可读性 :达文西的发明虽然荒诞,但它清晰地展示了如何将不同的元素组合起来。在软件开发中,策略模式通过将算法封装在独立的类中,提高了代码的可读性和可理解性。例子: 在文本编辑器中,我们可能有多种文本格式化策略(如加粗、斜体、下划线等)。通过策略模式,我们可以清晰地定义每种格式化策略,使得代码更加模块化和易于理解。

  5. 易于扩展 :达文西的"要你命3000"展示了如何通过组合不同的元素来创造新的发明。在软件开发中,策略模式使得添加新的算法变得非常容易,而不需要修改现有的代码。例子: 在电子商务平台中,我们可能需要支持多种配送策略(如快递、平邮、同城配送等)。通过策略模式,我们可以轻松地添加新的配送策略,而不需要修改现有的订单处理代码。

  6. 解耦 :达文西的发明展示了如何将不同的元素组合起来,而不需要它们之间有直接的依赖关系。在软件开发中,策略模式将算法的实现与使用算法的客户端解耦,提高了系统的灵活性。例子: 在数据库访问层中,我们可能需要支持多种数据库操作(如查询、更新、删除等)。通过策略模式,我们可以将数据库操作的实现与使用这些操作的业务逻辑解耦,使得数据库访问层更加灵活和可维护。

三、策略模式示例

在代码中,我一般很少直接用策略模式,一般直接使用策略枚举:

  1. 武器策略接口(约束算法的行为):

    java 复制代码
    //武器策略接口
    public interface WeaponStrategy {
        void attack();
    }
  2. 武器的实现类(具体的算法):

    java 复制代码
    //西瓜刀武器策略
    public class WatermelonKnifeStrategy implements WeaponStrategy {
        @Override
        public void attack() {
            System.out.println("吃我一西瓜刀!");
        }
    }
    //链条武器策略
    public class ChainStrategy implements WeaponStrategy {
        @Override
        public void attack() {
            System.out.println("吃我一链条!");
        }
    }
    //火药武器策略
    public class GunpowderStrategy implements WeaponStrategy {
        @Override
        public void attack() {
            System.out.println("吃我一火药!");
        }
    }
  3. 武器组合(要你命3000):

    java 复制代码
    //武器库:枚举
    public enum BattleStrategyEnum {
        WATERMELON_KNIFE("watermelon_knife", new WatermelonKnifeStrategy()),
        CHAIN("chain", new ChainStrategy()),
        GUNPOWDER("gunpowder", new GunpowderStrategy());
    
        private final String key;
        private final WeaponStrategy strategy;
    
        BattleStrategyEnum(String key, WeaponStrategy strategy) {
            this.key = key;
            this.strategy = strategy;
        }
    
        public String getKey() {
            return key;
        }
    
        public WeaponStrategy getStrategy() {
            return strategy;
        }
    
        public static WeaponStrategy getStrategyByKey(String key) {
            for (BattleStrategyEnum strategy : BattleStrategyEnum.values()) {
                if (strategy.getKey().equals(key)) {
                    return strategy.getStrategy();
                }
            }
            throw new IllegalArgumentException("No strategy found for key: " + key);
        }
    }
  4. 达文西使用场景(根据传入的不同策略,执行对应的策略):

    java 复制代码
    public class BattleContext {
        private WeaponStrategy strategy;
    
        public BattleContext(String strategyKey) {
            this.strategy = BattleStrategyEnum.getStrategyByKey(strategyKey);
        }
    
        public void executeStrategy() {
            strategy.use();
        }
    }
  5. 场景(达文西大战金枪客)

    java 复制代码
    public class BattleSimulation {
        public static void main(String[] args) {
            // 模拟战斗场景
            System.out.println("Battle against Golden Gunman starts:");
            
            // 创建上下文对象
            BattleContext context;
    
            // 初期战斗策略
            context = new BattleContext(BattleStrategyEnum.WATERMELON_KNIFE.getKey());
            System.out.println("吃我一招:");
            context.executeStrategy();
            
            // 中期战斗策略
            context = new BattleContext(BattleStrategyEnum.CHAIN.getKey());
            System.out.println("再来一招:");
            context.executeStrategy();
            
            // 最终战斗策略
            context = new BattleContext(BattleStrategyEnum.GUNPOWDER.getKey());
            System.out.println("最后一招:");
            context.executeStrategy();
        }
    }
相关推荐
晨米酱3 分钟前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机5 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机6 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机6 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机6 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤6 小时前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机1 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴1 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript
李广坤1 天前
工厂模式
设计模式