Strategy design pattern
策略模式的概念、策略模式的结构、策略模式的优缺点、策略模式的使用场景、策略模式的实现示例、策略模式的源码分析
1、策略模式的概念
策略模式,即定义一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的用户。策略模式属于对象行为模式,它通过对算法进行封装,使把使用算法的责任和算法的实现分离开来,并委托给不同的对象对这些算法进行管理。
2、策略模式的结构
- 抽象策略角色:定义算法的行为,通常是接口或抽象类。
- 具体策略角色:实现抽象策略,实现其定义的算法行为。
- 上下文类:持有一个策略的引用,以委托的方式调用策略中算法的行为,并将其暴露给外部。
3、策略模式的优缺点
- 优点:
- 算法(策略)可以自由切换。
- 避免使用 if else 等多重条件判断。
- 扩展性良好。
- 缺点:
- 当策略过多时会导致系统类爆炸。
- 所有策略类都需对外暴露。
4、策略模式的使用场景
- 当系统需要动态的在几种算法中选择一种时,可将每个算法封装到策略类中。
- 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,可将每个条件分支用策略类代替。
- 系统中算法彼此完全独立,且要求对用户隐藏算法的具体实现细节时。
- 多个类只区别在表现行为不同,可以使用策略模式,在运行时动态选择要执行的行为。
5、策略模式的实现示例
抽象策略类:
public interface Equipment {
/**
* 定义算法
*/
void equipment();
}
具体策略一:
public class OneEquipment implements Equipment {
@Override
public void equipment() {
System.out.println("明朗之靴 德拉克撒的慕刃 赛瑞尔达的怨恨 幽梦之灵 夜之锋刃 守护天使");
}
}
具体策略二:
public class TwoEquipment implements Equipment {
@Override
public void equipment() {
System.out.println("水银之靴 星蚀 贪欲九头蛇 死亡之舞 玛莫提乌斯之噬 黑色切割着");
}
}
上下文:
public class Context {
private Equipment equipment;
public Context(Equipment equipment) {
this.equipment = equipment;
}
public void setEquipment(Equipment equipment) {
this.equipment = equipment;
}
public void equipment() {
this.equipment.equipment();
}
}
测试:
public class StrategyTest {
public static void main(String[] args) {
Context client = new Context(new OneEquipment());
client.equipment();
client.setEquipment(new TwoEquipment());
client.equipment();
}
}
测试结果:
明朗之靴 德拉克撒的慕刃 赛瑞尔达的怨恨 幽梦之灵 夜之锋刃 守护天使
水银之靴 星蚀 贪欲九头蛇 死亡之舞 玛莫提乌斯之噬 黑色切割着
6、策略模式的源码分析
spring security 中的 SecurityContextRepository 类的设计就用到了策略模式。其定义了操作 SecurityContext 的各种方法,然后交由子实现类去实现具体的操作细节。这是典型的策略模式的应用,同样,SessionRegistory 也用到了策略模式。
public interface SecurityContextRepository {
@Deprecated
SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder);
default Supplier<SecurityContext> loadContext(HttpServletRequest request) {
return () -> loadContext(new HttpRequestResponseHolder(request, null));
}
void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response);
boolean containsContext(HttpServletRequest request);
}
其子实现类 HttpSessionSecurityContextRepository、NullSecurityContextRepository、RequestAttributeSecurityContextRepository 等都是具体的策略类,当然我们也可以自定义策略类,如在实现分布式权限认证时。