~/app/articles/NORMAL

cat article/32.md

策略模式 (Strategy) 全面讲解

学习笔记
设计模式
策略模式
面向对象
Java
软件设计
编程实践

本文详细讲解了策略模式的概念、适用场景、实现方式以及与传统硬编码方式的对比,适合想要了解和学习面向对象设计模式的开发者阅读。

date: 2025-06-22T22:22:00 tags:

  • 面向对象
  • 设计模式
  • Java
  • 复习

策略模式 (Strategy) 全面讲解


1. 什么是策略模式?

策略模式是行为型设计模式,用于定义一系列算法,并将每个算法封装起来,使它们可以相互替换。

  • 核心思想:将算法与使用算法的客户端解耦,避免硬编码条件分支(如if-else或switch-case)。
  • 类比:
    • 出行方式选择(开车、骑车、步行,可随时切换)。
    • 支付方式选择(支付宝、微信、银行卡)。

🔹 适用场景

  • 需要动态切换算法或行为(如排序、支付、游戏AI策略)。
  • 避免使用多重条件判断(消除if-else地狱)。

2. 为什么需要策略模式?

问题场景(硬编码算法的缺陷)

假设有一个PaymentProcessor类,根据不同的支付方式执行不同逻辑:

// 传统方式:if-else硬编码
class PaymentProcessor {
    public void processPayment(String paymentType, double amount) {
        if ("Alipay".equals(paymentType)) {
            System.out.println("支付宝支付: " + amount);
        } else if ("WeChatPay".equals(paymentType)) {
            System.out.println("微信支付: " + amount);
        }
        // 新增支付方式需修改此类!
    }
}

问题:违反开闭原则(对扩展开放,对修改关闭)!

解决方案

将每种支付方式封装为独立策略,客户端动态选择。


3. 策略模式的结构

角色说明

  1. Strategy(策略接口):定义算法接口(如PaymentStrategy)。
  2. ConcreteStrategy(具体策略):实现具体算法(如AlipayStrategy)。
  3. Context(上下文):持有策略引用,负责调用策略(如PaymentProcessor)。

4. 示例代码(支付策略系统)

步骤1:定义策略接口

interface PaymentStrategy {
    void pay(double amount);
}

步骤2:实现具体策略

// 支付宝策略
class AlipayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("支付宝支付: " + amount);
    }
}

// 微信支付策略
class WeChatPayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("微信支付: " + amount);
    }
}

// 银行卡策略(新增策略无需修改原有代码)
class BankCardStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("银行卡支付: " + amount);
    }
}

步骤3:定义上下文(Context)

class PaymentProcessor {
    private PaymentStrategy strategy;

    // 设置策略(可动态切换)
    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    // 执行策略
    public void executePayment(double amount) {
        strategy.pay(amount);
    }
}

步骤4:客户端调用

public class Client {
    public static void main(String[] args) {
        PaymentProcessor processor = new PaymentProcessor();

        // 动态切换策略
        processor.setStrategy(new AlipayStrategy());
        processor.executePayment(100.0);  // 输出:支付宝支付: 100.0

        processor.setStrategy(new BankCardStrategy());
        processor.executePayment(200.0);  // 输出:银行卡支付: 200.0
    }
}

5. 关键点总结

🔹 策略模式 vs 条件分支

对比项if-else/switch-case策略模式
扩展性需修改原有代码新增策略类即可
可读性复杂逻辑时代码臃肿每个策略类职责单一

🔹 优点

  • 符合开闭原则:新增算法无需修改上下文。
  • 消除条件判断:避免复杂的if-else嵌套。
  • 算法复用:策略类可在不同上下文中共享。

🔹 缺点

  • 客户端需了解所有策略(可通过工厂模式结合解决)。

6. 互动实践

问题1:以下代码是否适合策略模式?为什么?

class Calculator {
    public int calculate(String operation, int a, int b) {
        switch (operation) {
            case "add": return a + b;
            case "subtract": return a - b;
            default: throw new IllegalArgumentException();
        }
    }
}

答案:适合!可将add、subtract等操作封装为策略类(如AddStrategy)。

问题2:如何用策略模式设计游戏角色攻击系统?

任务:

  • 策略接口:AttackStrategy(含attack()方法)。
  • 具体策略:MeleeAttack(近战)、RangedAttack(远程)。
  • 补全代码:
class GameCharacter {
    private ____ attackStrategy;  // 填空
    public void performAttack() { ____.attack(); }
}

7. 考试练习题

题目1(概念题)

策略模式的主要作用是?
A. 管理对象生命周期
B. 动态切换算法
C. 隐藏对象创建细节
D. 实现多继承

答案:B


题目2(代码填空)

补全策略模式的代码:

interface SortingStrategy {
    void sort(int[] data);
}

class QuickSort implements SortingStrategy {
    @Override
    public void sort(int[] data) {
        System.out.println("快速排序");
    }
}

class Sorter {
    private ____ strategy;  // 填空1
    
    public void setStrategy(____ strategy) {  // 填空2
        this.strategy = strategy;
    }
    
    public void executeSort(int[] data) {
        ____.sort(data);  // 填空3
    }
}

答案:

  1. SortingStrategy
  2. SortingStrategy
  3. strategy

题目3(设计题)

用策略模式设计一个文件压缩工具:

  • 策略接口:CompressionStrategy(含compress()方法)。
  • 具体策略:ZipCompression、RarCompression。
    要求:画出类图并写出关键代码。
$ comments --list (0)

// not signed in


// no comments yet