
结构型模式:装饰器模式
装饰器模式
1、装饰器模式:介绍
- 装饰器模式
- 在不改变原有类的基础上给类新增功能。
- 装饰器模式:能够避免继承导致的子类过多问题,也可以避免 AOP 带来的复杂性问题。
- 装饰器模式使用场景
new BufferedReader(new FileReader(" "))- Java 开发的字节流、字符流和文件流:一层嵌套一层,字节流转字符流等
2、装饰器模式:模拟场景
- 单点登录场景
- 以往使用的 SSO 是一个组件化通用的服务,不能在里面添加需要的用户访问验证功能
- 这时就可以使用装饰器模式扩充原有的单点登录服务,同时也保证原有功能不受破坏,可以继续使用。
3、装饰器模式:场景模拟代码
0、工程结构
lino-design-12.0
|——src
|——main
|--java
|--com.lino.design
|--HandlerInterceptor.java
|--SsoInterceptor.java
**1、模拟Spring的HandlerInterceptor **
/**
* @description: 自定义登录拦截接口
*/
public interface HandlerInterceptor {
/**
* 登录校验
*
* @param request 请求参数
* @param response 响应参数
* @param handler 拦截对象
* @return boolean
*/
boolean preHandle(String request, String response, Object handler);
}
**2、模拟单点登录功能 **
/**
* @description: sso登录拦截实现类
*/
public class SsoInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(String request, String response, Object handler) {
// 模拟获取cookie
String ticket = request.substring(1, 8);
// 模拟校验
return ticket.equals("success");
}
}
4、装饰器模式:代码实现
- 装饰器主要解决:直接继承时因功能的不断横向扩展导致子类膨胀的问题。
- 抽象构建角色(Component):定义抽象接口
- 具体构建角色(ConcreteComponent):实现抽象接口,可以是一组
- 装饰角色(Decorator):定义抽象类并继承接口中的方法,保证一致性
- 具体装饰角色(ConcreteDecorator):扩展装饰具体的实现逻辑
0、工程结构
lino-design-11.0
|——src
|——main
|--java
|--com.lino.decorator
|--LoginSsoDecorator.java
|--SsoDecorator.java
|——test
|--java
|--com.lino.test
|--Test.java

- 重点的类是
SsoDecorator:它表示一个抽象类主要完成了对接口HandlerInterceptor的继承 - 当装饰角色继承接口后,会提供构造函数
SsoDecorator(HandlerInterceptor handlerInterceptor)- 入参是继承的接口实现类,可以很方便地扩展出不同的功能组件
1、抽象类装饰角色
- 装饰类中,有三点需要注意:
- 继承了处理接口,提供了构造函数,覆盖了方法
preHandler
- 继承了处理接口,提供了构造函数,覆盖了方法
import com.lino.design.HandlerInterceptor;
/**
* @description: 抽象类装饰角色
*/
public 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);
}
}
2、装饰角色逻辑实现
- 在具体的装饰类实现中,继承了装饰类
SsoDecorator,现在可以扩展方法preHandler的功能。 - 这里只关心扩展部分的功能,同时不会影响原有类的核心服务,也不会因为使用继承方式而导致出现多余子类,增加了整体的灵活性
import com.lino.design.HandlerInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @description: 装饰角色逻辑实现
*/
public class LoginSsoDecorator extends SsoDecorator {
/**
* 日志
*/
private Logger logger = LoggerFactory.getLogger(LoginSsoDecorator.class);
/**
* 用户集合
*/
private static Map<String, String> authMap = new ConcurrentHashMap<String, String>();
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);
}
}
3、单元测试
- 测试了装饰器模式的使用
- 通过将原有单点登录类
new SsoInterceptor()传递给装饰器,让装饰器可以执行扩充的功能 - 同时,传递者和装饰器都可以是多组的
- 通过将原有单点登录类
import com.lino.decorator.LoginSsoDecorator;
import com.lino.design.SsoInterceptor;
/**
* @description: 测试类
*/
public class Test {
@org.junit.Test
public void testLoginSsoDecorator() {
LoginSsoDecorator ssoDecorator = new LoginSsoDecorator(new SsoInterceptor());
String request = "1successhuahua";
boolean success = ssoDecorator.preHandle(request, "ewcdqwt40liuiu", "t");
System.out.println("登录校验:" + request + (success ? " 放行" : " 拦截"));
}
}
- 测试结果
14:36:41.328 [main] INFO com.lino.decorator.LoginSsoDecorator - 模拟单点登录方法访问拦截校验:huahua queryUserInfo
登录校验:1successhuahua 放行
5、装饰器模式:总结
- 装饰器模式满足单一职责原则
- 可以在自己的装饰类中完成功能逻辑的扩展而不影响主类。
- 可以按需在运行时添加和删除这部分逻辑
- 装饰器模式实现的重点是对抽象类继承接口方式的使用
- 同时设定被继承的接口可以通过构造函数传递其实现类,由此增加扩展性,并重写方法中可以通过父类实现的功能。
版权声明:本文为qq_35692974原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。