策略模式(Strategy Pattern)
文章目录
一. 概念
定义一些列算法,并将每种算法策略分别放在独立的类,以使算法的对象相互替换
二. 使用场合
- 多个类只在行为上不同,并在运算时切换不同行为时。策略模式提供一种对这些行为进行配置类的方法
- 一个类定义了许多行为,这些行为在其操作中表现为多个条件语句。将相关的条件分支移到它们自己的Strategy类中,而不是使用许多条件分支
- 若算法在上下文逻辑关联不大,且不是特别重要时,可用策略模式将业务和算法分开
ps:java
中的使用
- 对
java.util.Comparator#compare()
的调用来自Collections#sort()
.javax.servlet.http.HttpServlet
:service()
方法, 还有所有接受HttpServletRequest
和HttpServletResponse
对象作为参数的doXXX()
方法。javax.servlet.Filter#doFilter()
三. 优点及缺点
- 优点:
- 可在运行切换策略
- 算法实现和算法代码分开
- 开闭原则,无需改上下文源码情况下,引入新策略
- 缺点:如果策略极少,引入策略会使程序复杂
四. 结构图
五. 小试牛刀
5.1 问题
旅游对于我们来说是一种享受,那么选择合适的交通也极为重要
问题抛出:
根据不同的交通工具制定不同的策略,以便旅游时自己可任意选择
5.2 uml
5.3 代码实现
⭐️ 依赖
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.7.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
⭐️ Travel
旅游类:可筛选和切换策略
package com.zhanghp.demo01;
/**
* @author zhanghp
* @date 2022-08-30 15:09
*/
public class Travel {
private TravelStrategy travelStrategy;
public Travel(TravelStrategy strategy) {
this.travelStrategy = strategy;
}
public void transprotation(){
this.travelStrategy.excute();
}
public void changeStrategy(TravelStrategy strategy){
this.travelStrategy = strategy;
}
}
⭐️ TravelStrategy
旅游交通工具策略接口类:定义统一的旅游交通工具实现方法
package com.zhanghp.demo01;
/**
* @author zhanghp
* @date 2022-08-30 15:07
*/
public interface TravelStrategy {
void excute();
}
⭐️ Car
And Bike
交通工具类:实现交通方法
@Slf4j
public class Car implements TravelStrategy{
@Override
public void excute() {
log.info("Car to travel");
}
}
@Slf4j
public class Bike implements TravelStrategy{
@Override
public void excute() {
log.info("Bike to travel");
}
}
5.4 UT测试用例
-
代码
@Slf4j public class App { public static void main(String[] args) { Travel travel = new Travel(new Car()); travel.transprotation(); log.info(" <--- change Travel Transportation --->"); travel.changeStrategy(new Bike()); travel.transprotation(); } } @Slf4j public class TravelTest { @Test void travel(){ Assertions.assertDoesNotThrow(() -> {App.main(new String[]{});}); }
-
结果输出
- Car to travel - <--- change Travel Transportation ---> - Bike to travel
六. 参考资料及源码地址
-
Refactoring GURU:https://refactoring.guru/design-patterns/strategy
-
iluwater:https://github.com/iluwatar/java-design-patterns/blob/master/strategy/README.md
🌵源码:https://gitee.com/zhp1221/design_pattern/tree/master/lab_06_strategy
demo01
->lambda包
-> TavelEnumLambda:通过枚举实现接口来进行策略配置
demo02
:重构大师的示例代码有兴趣自行研究