0123_策略模式(Strategy)

策略模式(Strategy)

意图

定义一系列算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

UML 图

Strategy

优点

  1. 开闭原则:可以在不修改上下文的情况下引入新的策略
  2. 避免条件语句:消除了大量的if-else或switch-case语句
  3. 算法复用:不同的上下文可以共享同一个策略对象
  4. 灵活性:运行时可以动态切换算法
  5. 职责分离:将算法的实现与使用分离

缺点

  1. 客户端必须了解策略:客户端需要知道不同策略的区别
  2. 增加对象数量:每个策略都是一个类,可能增加系统复杂度
  3. 通信开销:策略和上下文之间可能需要传递数据
  4. 策略选择逻辑:可能需要额外的逻辑来选择合适策略

代码示例

以人类和机器人的作战策略为例,不同的战斗情境下采用不同的战术策略:

1. 策略接口 (Strategy Interface)

// 战斗策略接口
public interface CombatStrategy {
    void executeStrategy(String unitName, String enemyType);
    String getStrategyName();
}

2. 具体策略 (Concrete Strategies)

// 近战策略 - 针对人类战士优化
public class MeleeStrategy implements CombatStrategy {
    @Override
    public void executeStrategy(String unitName, String enemyType) {
        System.out.println("⚔️ " + unitName + " 执行近战策略: " +
                         "快速接近" + enemyType + ",使用冷兵器进行肉搏战");
    }
    
    @Override
    public String getStrategyName() {
        return "近战突击";
    }
}

// 远程策略 - 针对机器人射手优化
public class RangedStrategy implements CombatStrategy {
    @Override
    public void executeStrategy(String unitName, String enemyType) {
        System.out.println("🏹 " + unitName + " 执行远程策略: " +
                         "保持安全距离,使用枪械或弓箭攻击" + enemyType);
    }
    
    @Override
    public String getStrategyName() {
        return "远程打击";
    }
}

// 防御策略 - 通用防御战术
public class DefenseStrategy implements CombatStrategy {
    @Override
    public void executeStrategy(String unitName, String enemyType) {
        System.out.println("🛡️ " + unitName + " 执行防御策略: " +
                         "建立防御阵型,抵挡" + enemyType + "的进攻");
    }
    
    @Override
    public String getStrategyName() {
        return "坚固防御";
    }
}

3. 上下文类 (Context Class)

// 作战单位 - 上下文
public class CombatUnit {
    private String name;
    private String type; // "人类" 或 "机器人"
    private CombatStrategy strategy;
    
    public CombatUnit(String name, String type, CombatStrategy initialStrategy) {
        this.name = name;
        this.type = type;
        this.strategy = initialStrategy;
    }
    
    public void setStrategy(CombatStrategy newStrategy) {
        this.strategy = newStrategy;
        System.out.println(name + " 切换策略为: " + newStrategy.getStrategyName());
    }
    
    public void engageEnemy(String enemyType) {
        System.out.println("\n" + type + "单位 " + name + " 开始作战!");
        strategy.executeStrategy(name, enemyType);
    }
    
    public String getCurrentStrategy() {
        return strategy.getStrategyName();
    }
}

4. 客户端代码 (Client Code)

// 战术指挥系统
public class CombatCommandSystem {
    public static void main(String[] args) {
        // 创建不同的策略
        CombatStrategy melee = new MeleeStrategy();
        CombatStrategy ranged = new RangedStrategy();
        CombatStrategy defense = new DefenseStrategy();
        
        // 创建作战单位
        CombatUnit humanSoldier = new CombatUnit("张三", "人类", melee);
        CombatUnit robotSniper = new CombatUnit("T-800", "机器人", ranged);
        CombatUnit mixedUnit = new CombatUnit("突击小队", "混合", defense);
        
        // 执行不同策略
        humanSoldier.engageEnemy("机器人步兵");
        robotSniper.engageEnemy("人类侦察兵");
        mixedUnit.engageEnemy("敌方混合部队");
        
        // 动态切换策略
        System.out.println("\n=== 战场形势变化,调整策略 ===");
        humanSoldier.setStrategy(ranged);
        humanSoldier.engageEnemy("空中单位");
        
        robotSniper.setStrategy(melee);
        robotSniper.engageEnemy("近距离目标");
        
        mixedUnit.setStrategy(melee);
        mixedUnit.engageEnemy("突破防线");
        
        // 展示当前策略状态
        System.out.println("\n=== 各单位当前策略 ===");
        System.out.println("人类士兵: " + humanSoldier.getCurrentStrategy());
        System.out.println("机器人: " + robotSniper.getCurrentStrategy());
        System.out.println("混合小队: " + mixedUnit.getCurrentStrategy());
        
        // 重用策略对象
        System.out.println("\n=== 新单位重用现有策略 ===");
        CombatUnit newRobot = new CombatUnit("T-1000", "机器人", ranged);
        newRobot.engageEnemy("重型目标");
    }
}

在Java标准库中的应用

策略模式在Java标准库中有广泛应用:

  1. Comparator接口

    // 不同的排序策略
    List<String> names = Arrays.asList("John", "Alice", "Bob");
    
    // 字母顺序策略
    names.sort(Comparator.naturalOrder());
    
    // 长度排序策略
    names.sort(Comparator.comparingInt(String::length));
    
    // 自定义排序策略
    names.sort((a, b) -> b.compareTo(a)); // 逆序
    
  2. ThreadPoolExecutor拒绝策略

    ThreadPoolExecutor executor = new ThreadPoolExecutor(
        2, 4, 60, TimeUnit.SECONDS, 
        new LinkedBlockingQueue<>(10),
        // 不同的拒绝策略
        new ThreadPoolExecutor.AbortPolicy() // 策略1: 抛出异常
        // new ThreadPoolExecutor.CallerRunsPolicy() // 策略2: 调用者运行
        // new ThreadPoolExecutor.DiscardPolicy() // 策略3: 直接丢弃
    );
    
  3. 加密策略

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    // 不同的加密模式策略
    cipher.init(Cipher.ENCRYPT_MODE, key); // 加密策略
    cipher.init(Cipher.DECRYPT_MODE, key); // 解密策略
    
  4. 布局管理器(Swing)

    JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout()); // 边界布局策略
    panel.setLayout(new FlowLayout());   // 流式布局策略
    panel.setLayout(new GridLayout(2,2)); // 网格布局策略
    

总结

策略模式通过将算法封装在独立的策略类中,实现了算法的灵活切换和复用。在人类和机器人的作战示例中,不同的战斗单位可以根据战场形势动态选择合适的战术策略,而无需修改单位本身的代码。这种模式特别适用于需要多种算法变体、希望避免使用条件语句、以及需要在运行时选择算法的场景。

posted @ 2025-09-09 07:07  庞去广  阅读(16)  评论(0)    收藏  举报