【源码分析设计模式 10】SpringMVC 中的建造者模式,mybatis 技术原理 pdf
@Override
public void roofed() {
System.out.println(" 普通房子屋顶 ");
}
}
(2)HighBuilding?
package designMode.advance.builder;
public class HighBuilding extends HouseBuilder {
@Override
public void buildBasic() {
System.out.println(" 高楼的打地基 100 米 ");
}
@Override
public void buildWalls() {
System.out.println(" 高楼的砌墙 20cm ");
}
@Override
public void roofed() {
System.out.println(" 高楼的透明屋顶 ");
}
}
4、指挥者 HouseDirector?
package designMode.advance.builder;
public class HouseDirector {
HouseBuilder houseBuilder = null;
//构造器传入 houseBuilder
public HouseDirector(HouseBuilder houseBuilder) {
this.houseBuilder = houseBuilder;
}
//通过 setter 传入 houseBuilder
public void setHouseBuilder(HouseBuilder houseBuilder) {
this.houseBuilder = houseBuilder;
}
//如何处理建造房子的流程,交给指挥者
public House constructHouse() {
houseBuilder.buildBasic();
houseBuilder.buildWalls();
houseBuilder.roofed();
return houseBuilder.buildHouse();
}
}
5、测试类
package designMode.advance.builder;
public class Client {
public static void main(String[] args) {
//盖普通房子
CommonHouse commonHouse = new CommonHouse();
//准备创建房子的指挥者
HouseDirector houseDirector = new HouseDirector(commonHouse);
//完成盖房子,返回产品(普通房子)
House house = houseDirector.constructHouse();
System.out.println("--------------------------");
//盖高楼
HighBuilding highBuilding = new HighBuilding();
//重置建造者
houseDirector.setHouseBuilder(highBuilding);
//完成盖房子,返回产品(高楼)
houseDirector.constructHouse();
}
}
6、控制台输出
六、建造者模式在 SpringMVC 中的实现
=====================
1、在 springMVC 中,我们就可以看到建造者模式的身影。
springMVC 在构建 UriComponents 的内容时,就用到了建造者模式,我们先来看看 UriComponents 这个类是提供了哪些 Components
public abstract class UriComponents implements Serializable {
private static final String DEFAULT_ENCODING = "UTF-8";
// 用于分割 uri 的正则表达式,下面会说到
private static final Pattern NAMES_PATTERN = Pattern.compile("\{([^/]+?)\}");
private final String scheme;
private final String fragment;
protected UriComponents(String scheme, String fragment) {
this.scheme = scheme;
this.fragment = fragment;
}
// 多个 Components 对应的 getter 方法
/**
返回 URL 的 scheme.
*/
public final String getScheme() {
return this.scheme;
}
/**
返回 URL 的 fragment.
*/
public final String getFragment() {
return this.fragment;
}
/**
返回 URL 的 schemeSpecificPar
*/
public abstract String getSchemeSpecificPart();
/**
返回 userInfo
*/
public abstract String getUserInfo();
/**
返回 URL 的 host
*/
public abstract String getHost();
/**
返回 URL 的 port
*/
public abstract int getPort();
/**
返回 URL 的 path
*/
public abstract String getPath();
/**
返回 URL 的 path 部分的集合
*/
public abstract List<String> getPathSegments();
/**
返回 URL 的 query 部分
*/
public abstract String getQuery();
/**
返回 URL 的 query 参数 map
*/
public abstract MultiValueMap<String, String> getQueryParams();
/**
将 URL 的 components 用特定的编码规则编码并返回,默认为 utf-8
*/
public final UriComponents encode() {
try {
return encode(DEFAULT_ENCODING);
}
catch (UnsupportedEncodingException ex) {
// should not occur
throw new IllegalStateException(ex);
}
}
/**
编码的抽象方法,传入相应的编码规则
*/
public abstract UriComponents encode(String encoding) throws UnsupportedEncodingException;
/**
将 URL 中的模板参数换成对应的值
*/
public final UriComponents expand(Map<String, ?> uriVariables) {
Assert.notNull(uriVariables, "'uriVariables' must not be null");
return expandInternal(new MapTemplateVariables(uriVariables));
}
/**
将 URL 中的模板参数换成对应的值,输入为数组
*/
public final UriComponents expand(Object... uriVariableValues) {
Assert.notNull(uriVariableValues, "'uriVariableValues' must not be null");
return expandInternal(new VarArgsTemplateVariables(uriVariableValues));
}
/**
将 URL 中的模板参数换成对应的值,输入为 UriTemplateVariables
*/
public final UriComponents expand(UriTemplateVariables uriVariables) {
Assert.notNull(uriVariables, "'uriVariables' must not be null");
return expandInternal(uriVariables);
}
/**
将 URL 中的模板参数换成对应的值的最终的实现方法
*/
abstract UriComponents expandInternal(UriTemplateVariables uriVariables);
/**
处理 URL
*/
public abstract UriComponents normalize();
/**
返回 URL 的 string
*/
public abstract String toUriString();
/**
返回 URI 格式的方法
*/
public abstract URI toUri();
@Override
public final String toString() {
return toUriString();
}
/**
将这些 Components 的值赋给其 builder 类
*/
protected abstract void copyToUriComponentsBuilder(UriComponentsBuilder builder);
上面的代码不包括 UriComponents 类下其余的静态辅助方法,单单从此类的包含多种 components 中,就可以看出 UriComponents 的复杂程度。这些 components 大都对应了 url 的某个部分,能帮助 springMVC 对请求的 url 内容进行识别。springMVC 就是通过将 uri 构建成这个类,再对 uri 进行处理的。
2、UriComponentsBuilder
那么 springMVC 究竟是如何让请求的 uri 生成相应的 UriComponents 类呢?就要看看 UriComponentsBuilder 这个类了。
首先看看它的两个构造函数:
/**
默认构造方法,其中 path 的构造类为 CompositePathComponentBuilder,它为 UriComponentsBuilder 的内部静态类,主要实现对 url 的 path 部分进行构造。
*/
protected UriComponentsBuilder() {
this.pathBuilder = new CompositePathComponentBuilder();
}
/**
创建一个传入 UriComponentsBuilder 类的深拷贝对象
*/
protected UriComponentsBuilder(UriComponentsBuilder other) {
this.scheme = other.scheme;
this.ssp = other.ssp;
this.userInfo = other.userInfo;
this.host = other.host;
this.port = other.port;
this.pathBuilder = other.pathBuilder.cloneBuilder();
this.queryParams.putAll(other.queryParams);
this.fragment = other.fragment;
}
由于 url 的 path 部分是比较复杂的,这边 springMVC 用了内部类的方式,为 path 单独加了两个 builder 类,分别是 CompositePathComponentBuilder、FullPathComponentBuilder,这里就不扩展来说了。看完了 UriComponentsBuilder 的构造方法,我们来看它是如何将给定的 uri 生成为相应的 UriComponents 的。这里就从比较容易理解的 fromUriString 方法入手吧:
// 静态方法,从 uri 的字符串中获得 uri 的各种要素
public static UriComponentsBuilder fromUriString(String uri) {
Assert.notNull(uri, "URI must not be null");
// 利用正则表达式,获得 uri 的各个组成部分
Matcher matcher = URI_PATTERN.matcher(uri);
if (matcher.matches()) {
UriCompone
ntsBuilder builder = new UriComponentsBuilder();
// 获得对应要素的字符串
String scheme = matcher.group(2);
String userInfo = matcher.group(5);
String host = matcher.group(6);
String port = matcher.group(8);
String path = matcher.group(9);
String query = matcher.group(11);
String fragment = matcher.group(13);
// uri 是否透明的标志位
boolean opaque = false;
// uri 存在 scheme 且后面不跟:/则为不透明 uri
例如 mailto:java-net@java.sun.com
if (StringUtils.hasLength(scheme)) {
String rest = uri.substring(scheme.length());
if (!rest.startsWith(":/")) {
opaque = true;
}
评论