Java 中的策略模式:使用可互换算法简化对象行为
大约 4 分钟
也称为
- 策略
策略设计模式的意图
在 Java 中定义一组算法,将每个算法封装起来,并使它们可以互换,以使用策略设计模式来增强软件开发。策略允许算法独立于使用它的客户端而变化。
策略模式的详细说明及现实世界示例
现实世界示例
Java 中策略设计模式的一个实际现实世界示例体现在汽车导航系统中,在导航系统中,算法的灵活性至关重要。不同的导航算法(例如最短路线、最快路线和风景路线)可用于确定从一个位置到另一个位置的最佳路径。每种算法都封装了一种特定策略来计算路线。用户(客户端)可以根据自己的喜好在这几种算法之间切换,而无需更改导航系统本身。这使得在同一个系统中能够灵活地使用可互换的导航策略。
通俗易懂
策略模式允许在运行时选择最合适的算法。
维基百科说
在计算机编程中,策略模式(也称为策略模式)是一种行为型软件设计模式,它允许在运行时选择算法。
Java 中策略模式的编程示例
杀死巨龙是一项危险的工作。随着经验的积累,它变得更容易。经验丰富的巨龙杀手针对不同类型的巨龙制定了不同的战斗策略。
让我们探索如何在 Java 中实现 DragonSlayingStrategy
接口,展示策略模式的各种应用。
@FunctionalInterface
public interface DragonSlayingStrategy {
void execute();
}
@Slf4j
public class MeleeStrategy implements DragonSlayingStrategy {
@Override
public void execute() {
LOGGER.info("With your Excalibur you sever the dragon's head!");
}
}
@Slf4j
public class ProjectileStrategy implements DragonSlayingStrategy {
@Override
public void execute() {
LOGGER.info("You shoot the dragon with the magical crossbow and it falls dead on the ground!");
}
}
@Slf4j
public class SpellStrategy implements DragonSlayingStrategy {
@Override
public void execute() {
LOGGER.info("You cast the spell of disintegration and the dragon vaporizes in a pile of dust!");
}
}
这里就是强大的 DragonSlayer
,他可以根据对手选择他的战斗策略。
public class DragonSlayer {
private DragonSlayingStrategy strategy;
public DragonSlayer(DragonSlayingStrategy strategy) {
this.strategy = strategy;
}
public void changeStrategy(DragonSlayingStrategy strategy) {
this.strategy = strategy;
}
public void goToBattle() {
strategy.execute();
}
}
最后,这是 DragonSlayer
的实际操作。
@Slf4j
public class App {
private static final String RED_DRAGON_EMERGES = "Red dragon emerges.";
private static final String GREEN_DRAGON_SPOTTED = "Green dragon spotted ahead!";
private static final String BLACK_DRAGON_LANDS = "Black dragon lands before you.";
public static void main(String[] args) {
// GoF Strategy pattern
LOGGER.info(GREEN_DRAGON_SPOTTED);
var dragonSlayer = new DragonSlayer(new MeleeStrategy());
dragonSlayer.goToBattle();
LOGGER.info(RED_DRAGON_EMERGES);
dragonSlayer.changeStrategy(new ProjectileStrategy());
dragonSlayer.goToBattle();
LOGGER.info(BLACK_DRAGON_LANDS);
dragonSlayer.changeStrategy(new SpellStrategy());
dragonSlayer.goToBattle();
// Java 8 functional implementation Strategy pattern
LOGGER.info(GREEN_DRAGON_SPOTTED);
dragonSlayer = new DragonSlayer(
() -> LOGGER.info("With your Excalibur you severe the dragon's head!"));
dragonSlayer.goToBattle();
LOGGER.info(RED_DRAGON_EMERGES);
dragonSlayer.changeStrategy(() -> LOGGER.info(
"You shoot the dragon with the magical crossbow and it falls dead on the ground!"));
dragonSlayer.goToBattle();
LOGGER.info(BLACK_DRAGON_LANDS);
dragonSlayer.changeStrategy(() -> LOGGER.info(
"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!"));
dragonSlayer.goToBattle();
// Java 8 lambda implementation with enum Strategy pattern
LOGGER.info(GREEN_DRAGON_SPOTTED);
dragonSlayer.changeStrategy(LambdaStrategy.Strategy.MELEE_STRATEGY);
dragonSlayer.goToBattle();
LOGGER.info(RED_DRAGON_EMERGES);
dragonSlayer.changeStrategy(LambdaStrategy.Strategy.PROJECTILE_STRATEGY);
dragonSlayer.goToBattle();
LOGGER.info(BLACK_DRAGON_LANDS);
dragonSlayer.changeStrategy(LambdaStrategy.Strategy.SPELL_STRATEGY);
dragonSlayer.goToBattle();
}
}
程序输出
13:06:36.631 [main] INFO com.iluwatar.strategy.App -- Green dragon spotted ahead!
13:06:36.634 [main] INFO com.iluwatar.strategy.MeleeStrategy -- With your Excalibur you sever the dragon's head!
13:06:36.634 [main] INFO com.iluwatar.strategy.App -- Red dragon emerges.
13:06:36.634 [main] INFO com.iluwatar.strategy.ProjectileStrategy -- You shoot the dragon with the magical crossbow and it falls dead on the ground!
13:06:36.634 [main] INFO com.iluwatar.strategy.App -- Black dragon lands before you.
13:06:36.634 [main] INFO com.iluwatar.strategy.SpellStrategy -- You cast the spell of disintegration and the dragon vaporizes in a pile of dust!
13:06:36.634 [main] INFO com.iluwatar.strategy.App -- Green dragon spotted ahead!
13:06:36.634 [main] INFO com.iluwatar.strategy.App -- With your Excalibur you severe the dragon's head!
13:06:36.634 [main] INFO com.iluwatar.strategy.App -- Red dragon emerges.
13:06:36.635 [main] INFO com.iluwatar.strategy.App -- You shoot the dragon with the magical crossbow and it falls dead on the ground!
13:06:36.635 [main] INFO com.iluwatar.strategy.App -- Black dragon lands before you.
13:06:36.635 [main] INFO com.iluwatar.strategy.App -- You cast the spell of disintegration and the dragon vaporizes in a pile of dust!
13:06:36.635 [main] INFO com.iluwatar.strategy.App -- Green dragon spotted ahead!
13:06:36.637 [main] INFO com.iluwatar.strategy.LambdaStrategy -- With your Excalibur you severe the dragon's head!
13:06:36.637 [main] INFO com.iluwatar.strategy.App -- Red dragon emerges.
13:06:36.637 [main] INFO com.iluwatar.strategy.LambdaStrategy -- You shoot the dragon with the magical crossbow and it falls dead on the ground!
13:06:36.637 [main] INFO com.iluwatar.strategy.App -- Black dragon lands before you.
13:06:36.637 [main] INFO com.iluwatar.strategy.LambdaStrategy -- You cast the spell of disintegration and the dragon vaporizes in a pile of dust!
何时在 Java 中使用策略模式
在以下情况下使用策略模式
- 您需要在一个对象中使用算法的不同变体,并且希望在运行时切换算法。
- 存在多个相关的类,它们只在行为上有所不同。
- 算法使用客户端不应该知道的的数据。
- 一个类定义了多种行为,这些行为以操作中的多个条件语句的形式出现。
策略模式 Java 教程
策略模式在 Java 中的现实世界应用
- Java 的
java.util.Comparator
接口是策略模式的常见示例。 - 在 GUI 框架中,布局管理器(例如 Java 的 AWT 和 Swing 中的布局管理器)是策略。
策略模式的优点和权衡
优点
- 重用相关的算法族。
- 扩展行为的替代方法,避免子类化。
- 避免使用条件语句来选择所需的行为。
- 允许客户端选择算法实现。
权衡
- 客户端必须了解不同的策略。
- 对象数量增加。