策略模式是一种定义一系列算法的方法,从概念上看,所有这些算法完成的都是相同的同坐,只是实现不同,他可以以相同的方式调用所有算法,减少了各种算法类与使用算法类之间的耦合
优点
-
策略模式的Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法的公共功能
-
策略模式简化了单元测试,每一个算法都有自己的类,可以通过自己的接口单独测试
使用场景
策略模式就是用来封装算法的,但在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性
- 对于只有一些行为不同的许多相似类,策略模式提供了一种方法去配置这么多类的行为
- 如果一个类定义了许多方法,并且在使用的时候需要很多的条件进行判断,可以使用策略模式把相关联的条件分支封装到策略类中
- 如果不想要客户端知道算法使用的数据,可以使用策略模式避免暴露算法指定的数据结构
策略模式知名类
Policy
实例
/**
*
* 策略接口.
*
*/
@FunctionalInterface
public interface DragonSlayingStrategy {
void execute();
}
/**
*
* 乱斗策略.
*
*/
public class MeleeStrategy implements DragonSlayingStrategy {
private static final Logger LOGGER = LoggerFactory.getLogger(MeleeStrategy.class);
@Override
public void execute() {
LOGGER.info("With your Excalibur you sever the dragon's head!");
}
}
/**
*
* 射弹策略.
*
*/
public class ProjectileStrategy implements DragonSlayingStrategy {
private static final Logger LOGGER = LoggerFactory.getLogger(ProjectileStrategy.class);
@Override
public void execute() {
LOGGER.info("You shoot the dragon with the magical crossbow and it falls dead on the ground!");
}
}
/**
*
* 法术策略.
*
*/
public class SpellStrategy implements DragonSlayingStrategy {
private static final Logger LOGGER = LoggerFactory.getLogger(SpellStrategy.class);
@Override
public void execute() {
LOGGER.info("You cast the spell of disintegration and the dragon vaporizes in a pile of dust!");
}
}
/**
*
* 使用不同的策略屠龙
*
*/
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();
}
}
/**
*
* 策略模式是一种可以在运行时选择使用算法的一种模式
* 在java8之前,各种策略需要被拆分成不同的类,开发人员不得不写大量的模板代码。在java8之后可以使用lambda表达式来使代码更具可读性
*
*/
public class App {
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
/**
* Program entry point
*
* @param args command line args
*/
public static void main(String[] args) {
// GoF Strategy pattern
LOGGER.info("Green dragon spotted ahead!");
DragonSlayer dragonSlayer = new DragonSlayer(new MeleeStrategy());
dragonSlayer.goToBattle();
LOGGER.info("Red dragon emerges.");
dragonSlayer.changeStrategy(new ProjectileStrategy());
dragonSlayer.goToBattle();
LOGGER.info("Black dragon lands before you.");
dragonSlayer.changeStrategy(new SpellStrategy());
dragonSlayer.goToBattle();
// Java 8 Strategy pattern
LOGGER.info("Green dragon spotted ahead!");
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 before you.");
dragonSlayer.changeStrategy(() -> LOGGER.info(
"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!"));
dragonSlayer.goToBattle();
}
}