策略模式
策略模式(Strategy Pattern)属于行为型模式。它把一系列的算法分别封装到对应的类中,并且这些类实现相同的接口,相互之间可以替换。
这算法体现了几个设计原则,第一、把变化的代码从不变的代码中分离出来;第二、针对接口编程而不是具体 类(定义了策略接口);第三、多用组合/聚合,少用继承(客户通过组合方式使用策略)。
策略模式的三个角色
- Context(环境类):也叫上下文,对策略进行二次封装,目的是避免高层模块对策略的直接调用。
- Strategy(抽象策略):通常情况下为一个接口,当各个实现类中存在着重复的逻辑时,则使用抽象类来封装这部分公共的代码,此时,策略模式看上去更像是模版方法模式。
- ConcreteStrategy(具体策略):具体策略角色通常由一组封装了算法的类来担任,这些类之间可以根据需要自由替换。
举一个栗子
假设我们要去上学,去学校的方式有两种,可以选择坐公交车,也可以选择骑自行车。现在用策略模式实现这一方法。
Strategy:抽象策略
package cn.personalweb.strategy;
public interface Strategy {
/**
* 策略算法族, 就是不同策略类实现这个接口用不同的算法方式.
*/
public void strategyAlgorithm();
}
Bus:具体策略公交车
实现Strategy
的strategyAlgorithm
方法,让其坐公交。
package cn.personalweb.strategy;
public class Bus implements Strategy{
@Override
public void strategyAlgorithm() {
System.out.println("坐公交车");
}
}
Cycle:具体策略骑自行车
实现Strategy
的strategyAlgorithm
方法,让其骑自行车。
package cn.personalweb.strategy;
public class Cycle implements Strategy{
@Override
public void strategyAlgorithm() {
System.out.println("骑自行车");
}
}
Context:环境类
内部聚合了Strategy
策略,travelStyle()
方法,根据传入的不同策略来执行不同的方法。
package cn.personalweb.strategy;
public class Context {
private Strategy strategy;
public Context() {
}
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void travelStyle() {
strategy.strategyAlgorithm();
}
}
Client:客户端
package cn.personalweb.strategy;
public class Client {
public static void main(String[] args) {
Bus bus = new Bus();
Cycle cycle = new Cycle();
Context context = new Context();
// 坐公交
context.setStrategy(bus);
context.travelStyle();
// 骑自行车
context.setStrategy(cycle);
context.travelStyle();
}
}
输出结果
做公交车
骑自行车
策略模式的注意事项和细节
-
策略模式的关键是:分析项目中变化部分与不变部分
-
策略模式的核心思想是:多用组合/聚合 少用继承;用行为类组合,而不是行为的继承。更有弹性
-
体现了“对修改关闭,对扩展开放”原则,客户端增加行为不用修改原有代码,只要添加一种策略(或者行为) 即可,避免了使用多重转移语句(if…else if…else)
-
提供了可以替换继承关系的办法: 策略模式将算法封装在独立的 Strategy 类中使得你可以独立于其 Context 改 变它,使它易于切换、易于理解、易于扩展
-
需要注意的是:每添加一个策略就要增加一个类,当策略过多是会导致类数目庞
参考资料:
尚硅谷 Java 设计模式课程笔记。