策略模式

作为程序员,可以选择多种编译器开发软件。
想象一下,你是一个旅行者,计划去不同的城市旅行。每个城市都有不同的交通方式:有些地方适合开车,有些地方适合骑自行车,还有些地方适合步行。
策略模式就像是你旅行时的交通方式选择方案。你可以根据目的地和个人喜好,灵活地选择最合适的交通方式。
案例-评分模块选择多种策略
需求:针对不同的应用类别和评分策略,编写不同的实现逻辑。
核心实现方式:策略模式
策略模式是一种行为设计模式,它定义了一系列算法,并将每个算法封装到独立的类中,使得它们可以相互替换。
在本项目的场景中,输入的参数是一致的(应用和用户的答案列表),并且每种实现逻辑区别较大,很适合使用策略模式。
1.定义策略接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
public interface ScoringStrategy {
UserAnswer doScore(List<String> choices, App app)throws Exception; }
|
2. 两种策略以及实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class CustomScoreScoringStrategy implements ScoringStrategy{ @Override public UserAnswer doScore(List<String> choices, App app) throws Exception{ } }
public class CustomTestScoringStrategy implements ScoringStrategy { @Override public UserAnswer doScore(List<String> choices, App app) throws Exception{ } }
|
3. 定义注解
声明式,在每个策略类中通过接口声明对应的生效条件,适合比较规律的策略选取场景。
注解:
1 2 3 4 5 6 7 8 9 10 11 12
| @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Component public @interface ScoringStrategyConfig {
int appType();
int scoringStrategy(); }
|
然后为其它两个实现类补充注解,根据不同策略,注解给不同的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @ScoringStrategyConfig(appType = 0, scoringStrategy = 0) public class CustomScoreScoringStrategy implements ScoringStrategy{ @Override public UserAnswer doScore(List<String> choices, App app) throws Exception{ } }
@ScoringStrategyConfig(appType = 1, scoringStrategy = 0) public class CustomTestScoringStrategy implements ScoringStrategy { @Override public UserAnswer doScore(List<String> choices, App app) throws Exception{ } }
|
4. 全局执行器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
@Service public class ScoringStrategyExecutor {
@Resource private List<ScoringStrategy> scoringStrategyList;
public UserAnswer doScore(List<String> choiceList, App app) throws Exception { Integer appType = app.getAppType(); Integer scoringStrategy = app.getScoringStrategy(); if (appType == null || scoringStrategy == null) { throw new BusinessException(ErrorCode.PARAMS_ERROR, "应用类型或评分策略不能为空"); }
for (ScoringStrategy strategy : scoringStrategyList) { if (strategy.getClass().isAnnotationPresent(ScoringSrategyConfig.class)) { ScoringSrategyConfig scoringSrategyConfig = strategy.getClass().getAnnotation(ScoringSrategyConfig.class); if(scoringSrategyConfig.appType()==appType && scoringSrategyConfig.scoringStrategy()==scoringStrategy){ return strategy.doScore(choiceList,app); } } } throw new BusinessException(ErrorCode.SYSTEM_ERROR, "应用配置有误,未找到匹配的策略"); }
}
|
因为用了 ScoringStrategyConfig 注解,所以这个实现类被加上了 component 注解,因此可以被spring 管理扫描到。 然后 @Resoure 注入的时候,会通过 ScoringStrategy 类型找到所有实现 ScoringStrategy 接口的实现类
这样使用注解,就不需要增加策略的时候修改全局执行器的代码,他可以根据注解里面的值自动选择相对于的策略实现