找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起
相关代码
模板方法设计模式
鸭子的行为可能各不相同(这就是可能需要变化的部分),如果让所有鸭子都实现一个行为接口,让行为各自不同,这是针对实现编程,依赖于实现,代码不能复用
针对接口编程,而不是针对实现编程
这里的接口是广义的接口,即包含接口和抽象类,现在我们还是需要一个行为接口,但是不由鸭子子类来实现该接口,而是编写一个实现了该行为接口的类,将这个行为类和鸭子类组合起来,利用多态,这样鸭子的行为就可以灵活多变,自由组合,代码也可以复用了
多用组合,少用继承
定义
定义了算法蔟,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户
优点
- 提供了对开闭原则的完美支持,可以在不改变原有系统的基础上选择具体的策略,也可以灵活地扩展新的策略
- 提供了管理相关的策略的方式
- 提供了可以替换继承关系的办法(组合)
- 可以避免使用多重条件转移语句
缺点
- 客户端必须直到所有的策略类,并自行决定使用哪一个策略类
- 策略模式会产生很多策略类(可以通过使用享元模式在一定程度上减少对象的数量)
Spring Security中的策略模式
用户登录信息存储策略
用户存储策略接口
1 2 3 4 5 6
| public interface SecurityContextHolderStrategy { void clearContext(); SecurityContext getContext(); void setContext(SecurityContext context); SecurityContext createEmptyContext(); }
|
其中一个以ThreadLocal方式存储用户登录信息的策略
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
| final class ThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy {
private static final ThreadLocal<SecurityContext> contextHolder = new ThreadLocal<>();
@Override public void clearContext() { contextHolder.remove(); }
@Override public SecurityContext getContext() { SecurityContext ctx = contextHolder.get(); if (ctx == null) { ctx = createEmptyContext(); contextHolder.set(ctx); } return ctx; }
@Override public void setContext(SecurityContext context) { Assert.notNull(context, "Only non-null SecurityContext instances are permitted"); contextHolder.set(context); }
@Override public SecurityContext createEmptyContext() { return new SecurityContextImpl(); }
}
|
用户信息存储容器类与存储策略类以组合方式协同工作
1 2 3 4 5 6 7 8 9
| public class SecurityContextHolder {
private static SecurityContextHolderStrategy strategy; public static void clearContext() { strategy.clearContext(); } }
|
Session并发管理
session策略接口
1 2 3 4 5 6
| public interface SessionAuthenticationStrategy {
void onAuthentication(Authentication authentication, HttpServletRequest request, HttpServletResponse response) throws SessionAuthenticationException;
}
|
AbstractAuthenticationProcessingFilter与session策略组合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public abstract class AbstractAuthenticationProcessingFilter extends GenericFilterBean implements ApplicationEventPublisherAware, MessageSourceAware { private SessionAuthenticationStrategy sessionStrategy = new NullAuthenticatedSessionStrategy(); private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException { this.sessionStrategy.onAuthentication(authenticationResult, request, response);
} public void setSessionAuthenticationStrategy(SessionAuthenticationStrategy sessionStrategy) { this.sessionStrategy = sessionStrategy; }
}
|
参考