0123_策略模式(Strategy)
策略模式(Strategy)
意图
定义一系列算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
UML 图

优点
- 开闭原则:可以在不修改上下文的情况下引入新的策略
- 避免条件语句:消除了大量的if-else或switch-case语句
- 算法复用:不同的上下文可以共享同一个策略对象
- 灵活性:运行时可以动态切换算法
- 职责分离:将算法的实现与使用分离
缺点
- 客户端必须了解策略:客户端需要知道不同策略的区别
- 增加对象数量:每个策略都是一个类,可能增加系统复杂度
- 通信开销:策略和上下文之间可能需要传递数据
- 策略选择逻辑:可能需要额外的逻辑来选择合适策略
代码示例
以人类和机器人的作战策略为例,不同的战斗情境下采用不同的战术策略:
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标准库中有广泛应用:
-
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)); // 逆序 -
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: 直接丢弃 ); -
加密策略
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); // 不同的加密模式策略 cipher.init(Cipher.ENCRYPT_MODE, key); // 加密策略 cipher.init(Cipher.DECRYPT_MODE, key); // 解密策略 -
布局管理器(Swing)
JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); // 边界布局策略 panel.setLayout(new FlowLayout()); // 流式布局策略 panel.setLayout(new GridLayout(2,2)); // 网格布局策略
总结
策略模式通过将算法封装在独立的策略类中,实现了算法的灵活切换和复用。在人类和机器人的作战示例中,不同的战斗单位可以根据战场形势动态选择合适的战术策略,而无需修改单位本身的代码。这种模式特别适用于需要多种算法变体、希望避免使用条件语句、以及需要在运行时选择算法的场景。

浙公网安备 33010602011771号