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

一、什么是策略模式

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

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

电影中,角色达文西以其机智和创造力,生动地展示了策略模式的精髓。面对电影中的反派角色金枪客的威胁,达文西,这位"聪明的发明家",迅速设计并制造了一种应对紧急情况的策略武器------"要你命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();
        }
    }
相关推荐
好好学习++1 小时前
【HF设计模式】06-命令模式
java·c++·设计模式·命令模式
咖啡の猫2 小时前
命令模式详解与应用
设计模式·命令模式
缺少动力的火车2 小时前
Java设计模式—观察者模式
java·观察者模式·设计模式
工一木子3 小时前
【HeadFirst系列之HeadFirst设计模式】第3天之观察者模式
java·观察者模式·设计模式·headfirst设计模式
LuckyLay4 小时前
Golang学习笔记_28——工厂方法模式
笔记·学习·设计模式·golang·工厂方法模式
想要打 Acm 的小周同学呀6 小时前
JDBCTemplate-模板设计模式和策略模式
设计模式·策略模式
荣--16 小时前
回顾我的软件开发经历:我与代码生成器的涅槃之路
设计模式·重构·c#·代码生成器
小王子102419 小时前
面向对象分析与设计Python版 GOF设计模式
python·设计模式·gof·面向对象分析与设计
智驾1 天前
C++,设计模式,【目录篇】
c++·设计模式