设计模式之策略模式
1、概念
(1)什么是策略模式?
定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换。策略模式包括策略接口、具体策略类及上下文角色。策略接口用来定义算法,如下方例子的StudyStatus;具体策略类用来实现策略接口,实现不同的算法,一般都会有多个策略类,如下方例子的BuddhismStudy、PlayAndStudy、OvernightStudy;上下文角色是用来屏蔽高层模块对策略的直接访问,起承上启下的作用。如下方例子中的CollegeStudents就是上下文角色,维护了一个对StudyStatus对象的引用。
(2)策略模式的应用
使用场景:
多个类只有算法或行为上稍有不同的场景。
算法需要自由切换的场景。
需要屏蔽算法规则的场景。
优点:
算法可以自由切换,对于算法的后期维护也很方便,不会影响原有代码。
避免使用多重条件判断(如果不用策略模式我们可能会使用多重条件语句,不利于维护)。
扩展性良好,增加一个策略只需实现接口即可。
缺点:
策略类数量会增多,每个策略都是一个类,复用的可能性很小。
所有的策略类都需要对外暴露,上层模块必须知道有哪些策略,然后才能决定使用哪一个策略。
2、策略模式的应用
实现大学生在学期的不同时段的学习状态。(都会学习,但学习状态不一样)
(1):定义策略接口
package com.example.designmode.strategy;
public interface StudyStatus {
String study();
}
(2):实现策略类
package com.example.designmode.strategy;
public class BuddhismStudy implements StudyStatus{
@Override
public String study() {
return "不去上课也行的,先嗨起来";
}
}
package com.example.designmode.strategy;
public class PlayAndStudy implements StudyStatus {
@Override
public String study() {
return "快要随堂测试了,我先补一补,可不能被老师当堂批评";
}
}
package com.example.designmode.strategy;
public class OvernightStudy implements StudyStatus {
@Override
public String study() {
return "快要期末考试了,我要加班加点学习,可不能挂科了";
}
}
(3):实现上下文角色
package com.example.designmode.strategy;
public class CollegeStudents {
private StudyStatus studyStatus;
public CollegeStudents(StudyStatus studyStatus) {
this.studyStatus = studyStatus;
}
public String study() {
return studyStatus.study();
}
}
(4):测试
package com.example.designmode.strategy;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class StrategyTest {
public static void main(String[] args) {
CollegeStudents collegeStudents = new CollegeStudents(new BuddhismStudy());
log.info("学期开始时大学生学习状态:{}", collegeStudents.study());
collegeStudents = new CollegeStudents(new PlayAndStudy());
log.info("快要随堂考时大学生学习状态:{}", collegeStudents.study());
collegeStudents = new CollegeStudents(new OvernightStudy());
log.info("快要期末考时大学生学习状态:{}", collegeStudents.study());
}
}
3、总结
总的来说,策略模式还是很简单的,只需要一个策略接口、策略实现类以及上下文角色就可以了。不过如果一个系统的策略多于四个,就需要考虑使用混合模式来解决策略类膨胀的问题。使用场景参考代码可以看JDK线程池的拒绝策略模式、DbUtils的查询方法对不同返回数据类型的处理(各种ResultHandler)、Java AWT中的LayoutManager,即布局管理器。
参考博客: