文章目录
装饰器模式使用的情景
- 装饰器模式使用的情景
- 装饰器模式使用的任务
- 装饰器模式实战
- 不使用装饰器模式写法
- 使用装饰器模式写法 (行动)
在不改原有类的基础上, 给类新增功能.
装饰器模式使用的任务单点登录模块, 一开始只是认证某个权限, 但随着业务的发展, 需要验证很多其他权限. 限定的任务是在不改变原有单点登录代码上 , 对验证权限进行扩展.
装饰器模式实战创建tutorials-12.0-0模块.
public interface HandlerInterceptor {
boolean preHandle(String request, String response, Object handler);
}
单点登录拦截器SsoInterceptor
public class SsoInterceptor implements HandlerInterceptor{
public boolean preHandle(String request, String response, Object handler) {
// 模拟登录获取cookie
String ticket = request.substring(1, 8);
// 模拟登录校验
return ticket.equals("success");
}
}
不使用装饰器模式写法
创建tutorials-12.0-1模块. queryUserInfo
代表有用户查询权限
public class LoginSsoDecorator extends SsoInterceptor {
private static Map authMap = new ConcurrentHashMap();
static {
authMap.put("huahua", "queryUserInfo");
authMap.put("doudou", "queryUserInfo");
}
@Override
public boolean preHandle(String request, String response, Object handler) {
// 模拟获取cookie
String ticket = request.substring(1, 8);
boolean success = ticket.equals("success");
if (!success) return false;
String userId = request.substring(8);
String method = authMap.get(userId);
return "queryUserInfo".equals(method);
}
}
测试类如下
public class ApiTest {
@Test
public void test_LoginSsoDecorator() {
LoginSsoDecorator ssoDecorator = new LoginSsoDecorator();
String request = "1successhuahua";
boolean success = ssoDecorator.preHandle(request, "ertert454", "t");
System.out.println("登录校验: " + request + (success ? "放行" : "拦截"));
}
}
使用装饰器模式写法 (行动)
使用装饰器模式的uml图 创建tutorials-12.0-2模块 创建SsoDecorator抽象装饰器
public abstract class SsoDecorator implements HandlerInterceptor {
private HandlerInterceptor handlerInterceptor;
public SsoDecorator() {
}
public SsoDecorator(HandlerInterceptor handlerInterceptor) {
this.handlerInterceptor = handlerInterceptor;
}
@Override
public boolean preHandle(String request, String response, Object handler) {
return handlerInterceptor.preHandle(request, response, handler);
}
}
创建LoginSsoDecorator 扩展服务
public class LoginSsoDecorator extends SsoDecorator {
private Logger logger = LoggerFactory.getLogger(LoginSsoDecorator.class);
private static Map authMap = new ConcurrentHashMap();
static {
authMap.put("huahua", "queryUserInfo");
authMap.put("doudou", "queryUserInfo");
}
public LoginSsoDecorator(HandlerInterceptor handlerInterceptor) {
super(handlerInterceptor);
}
@Override
public boolean preHandle(String request, String response, Object handler) {
boolean success = super.preHandle(request, response, handler);
if (!success) return false;
String userId = request.substring(8);
String method = authMap.get(userId);
logger.info("模拟单点登录方法访问拦截器校验: {} {}", userId, method);
// 模拟方法校验
return "queryUserInfo".equals(method);
}
}
扩展服务的preHandle方法, 既执行了父类的方法, 也执行了扩展的方法.
测试类 (结果)
public class ApiTest {
@Test
public void test_LoginSsoDecorator() {
LoginSsoDecorator ssoDecorator = new LoginSsoDecorator(new SsoInterceptor());
String request = "1successhuahua";
boolean success = ssoDecorator.preHandle(request, "ttttweee", "t");
System.out.println("登录校验: "+request+(success ? " 放行": "拦截"));
}
}
11:40:32.836 [main] INFO com.thc.design.LoginSsoDecorator - 模拟单点登录方法访问拦截器校验: huahua queryUserInfo
登录校验: 1successhuahua 放行
装饰器实现的重点是对抽象类继承接口方式的使用,同时设定被继承的接口可以通过构造函数传递其实现类,由此增加扩展性并重写方法里可以实现此部分父类实现的功能。