目录
前言
当我们对一个对象的某个操作,比如文本分析或者对象排序有多种算法,但是如果硬编码进它们的类中,将导致出现后续扩展困难,复杂度较高等。策略模式提出了一种方法解决这种情况。
1 定义
Strategy(策略)模式:定义一系列算法,并把它们独立封装到类中,使它们可以相互替换,独立于使用它们的客户而变化。
2 适用性
- 当你使用的对象中,有多种可选择算法,并希望在运行时动态改变。
- 当你有许多仅在行为上有不同的相似类时。
- 如果你使用的算法在对象和上下文中关联不密切,你可以抽象出算法与对象隔离开。
3 结构
3.1 结构图
策略模式结构图如下:
3.2 参与者
- Context:客户使用的对象,可以使用多种策略执行一个行为。通常包含一个指向策略实例的指针。
- Strategy:策略接口,定义了一系列相似策略的抽象公共部分方法。
- ConcreteStrategyA,ConcreteStrategyB和ConcreteStrategyC:具体的策略类,封装了特定的策略方法。由context进行调用。
4 实际应用举例
java中排序接口Comparator就是一种策略模式,由我们根据我们的对象去实现不同的排序策略。
4.1 Context——List列表和StuContext
LIst可以作为我们的Context,里边存储的对象StuContext是需要根据不同策略进行排序的内部数据。
以ArrayList为例,内部排序方法如下:
可见是通过传入策略接口,来实现对不同策略的支持。
StuContext定义如下:
/**
* 策略支持的对象类
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class StuContext {
//名字
private String stuName;
//平均分数
private int avgScore;
//数学分数
private int mathSCore;
@Override
public String toString() {
return "StuContext{" +
"stuName='" + stuName + '\'' +
", avgScore=" + avgScore +
", mathSCore=" + mathSCore +
'}';
}
}
就是定义一个实体,包含内部属性:名称、平均成绩和数学成绩。
4.2 具体策略:ConcreteStrategyA和ConcreteStrategyB
定义具体的排序策略:
- 平均成绩降序排列:ConcreteStrategyA
- 数学成绩降序排列:ConcreteStrategyB
分别定义如下:
/**
* 策略A——按照平均分进行排名
*/
public class ConcreteStrategyA implements Comparator<StuContext> {
@Override
public int compare(StuContext o1, StuContext o2) {
return o2.getAvgScore() - o1.getAvgScore();
}
}
/**
* 策略B——按照数学成绩排名
*/
public class ConcreteStrategyB implements Comparator<StuContext> {
@Override
public int compare(StuContext o1, StuContext o2) {
return o2.getMathSCore() - o1.getMathSCore();
}
}
4.3 测试demo
代码如下:
执行结果:
5 总结
当需要在运行时经常改变算法,同时又希望算法和对象进行隔离,减少耦合,可以借鉴策略模式。
参考文献
[1]. 《设计模式》