# 第3节.Nacos中的装饰者设计模式的会用
# 一、装饰者模式的定义
装饰(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。 装饰(Decorator)模式的主要优点有:
- 装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用
- 通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
- 装饰器模式完全遵守开闭原则
其主要缺点是:装饰模式会增加许多子类,过度使用会增加程序得复杂性。
# 二、装饰者模式的使用场景
饰模式通常在以下几种情况使用:
- 当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类。
- 当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰模式却很好实现。
- 当对象的功能要求可以动态地添加,也可以再动态地撤销时。
# 三、Nacos中关于装饰者设计模式的使用
# 3.1、服务名称过滤器中的使用
ServiceNameFilter类用于适配1.x版本的客户端,在该类中获取到serviceName之后,会对原有的服务名称进行判断,从而对Request对象进行装饰,过滤器代码如下:
/**
* 服务名称过滤器
*/
public class ServiceNameFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
try {
String serviceName = request.getParameter(CommonParams.SERVICE_NAME);
if (StringUtils.isNotBlank(serviceName)) {
serviceName = serviceName.trim();
}
String groupName = request.getParameter(CommonParams.GROUP_NAME);
if (StringUtils.isBlank(groupName)) {
groupName = Constants.DEFAULT_GROUP;
}
// use groupName@@serviceName as new service name:
String groupedServiceName = serviceName;
if (StringUtils.isNotBlank(serviceName) && !serviceName.contains(Constants.SERVICE_INFO_SPLITER)) {
groupedServiceName = groupName + Constants.SERVICE_INFO_SPLITER + serviceName;
}
OverrideParameterRequestWrapper requestWrapper = OverrideParameterRequestWrapper.buildRequest(request);
requestWrapper.addParameter(CommonParams.SERVICE_NAME, groupedServiceName);
filterChain.doFilter(requestWrapper, servletResponse);
} catch (Exception e) {
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Service name filter error," + ExceptionUtil.getAllExceptionMsg(e));
}
}
}
其中,OverrideParameterRequestWrapper类则是一个装饰器的模式类,对我们的原始请求Request对象进行了装饰。
/**
* 请求装饰器去重写服务名称参数
*/
public class OverrideParameterRequestWrapper extends HttpServletRequestWrapper {
private Map<String, String[]> params = new HashMap<>();
public OverrideParameterRequestWrapper(HttpServletRequest request) {
super(request);
this.params.putAll(request.getParameterMap());
}
public static OverrideParameterRequestWrapper buildRequest(HttpServletRequest request) {
return new OverrideParameterRequestWrapper(request);
}
public static OverrideParameterRequestWrapper buildRequest(HttpServletRequest request, String name, String value) {
OverrideParameterRequestWrapper requestWrapper = new OverrideParameterRequestWrapper(request);
requestWrapper.addParameter(name, value);
return requestWrapper;
}
public static OverrideParameterRequestWrapper buildRequest(HttpServletRequest request,
Map<String, String[]> appendParameters) {
OverrideParameterRequestWrapper requestWrapper = new OverrideParameterRequestWrapper(request);
requestWrapper.params.putAll(appendParameters);
return requestWrapper;
}
@Override
public String getParameter(String name) {
String[] values = params.get(name);
if (values == null || values.length == 0) {
return null;
}
return values[0];
}
@Override
public Map<String, String[]> getParameterMap() {
return params;
}
@Override
public String[] getParameterValues(String name) {
return params.get(name);
}
public void addParameter(String name, String value) {
if (value != null) {
params.put(name, new String[] {value});
}
}
}