策略模式 (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. 策略模式的结构
角色说明
Strategy(策略接口):定义算法接口(如PaymentStrategy)。ConcreteStrategy(具体策略):实现具体算法(如AlipayStrategy)。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
}
}
答案:
SortingStrategySortingStrategystrategy
题目3(设计题)
用策略模式设计一个文件压缩工具:
- 策略接口:
CompressionStrategy(含compress()方法)。 - 具体策略:
ZipCompression、RarCompression。
要求:画出类图并写出关键代码。