}
@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 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()) {
UriComponentsBuilder 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;
}
}
builder.scheme(scheme);
// 如果为不透明uri,则具备ssp,需要设置ssp
if (opaque) {
String ssp = uri.substring(scheme.length()).substring(1);
if (StringUtils.hasLength(fragment)) {
ssp = ssp.substring(0, ssp.length() - (fragment.length() + 1));
}
builder.schemeSpecificPart(ssp);
}
// 如果为绝对uri(通常意义上的uri),则设置各个component
else {
builder.userInfo(userInfo);
builder.host(host);
if (StringUtils.hasLength(port)) {
builder.port(port);
}
builder.path(path);
builder.query(query);
}
if (StringUtils.hasText(fragment)) {
builder.fragment(fragment);
}
return builder;
}
// 传入uri格式不对,抛出异常
else {
throw new IllegalArgumentException(“[” + uri + “] is not a valid URI”);
}
}
从上面的方法中,我们可以看到,UriComponentsBuilder从一个uri的字符串中,通过正则匹配的方式,获取到不同Components的信息并赋值。UriComponentsBuilder除了fromUriString这一种构建方法外,还提供fromUri,fromHttpUrl,fromHttpRequest,fromOriginHeader等好几种构建的方法,感兴趣的小伙伴可以自己去看。
那么在通过各种构建后,获取到了对应的Components信息,最后的一步,也是最重要的一步,build,将会返回我们需要的UriComponents类。UriComponentsBuilder提供了两类build方法,我们主要看默认的build方法:
/**
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
最后
为什么我不完全主张自学?
①平台上的大牛基本上都有很多年的工作经验了,你有没有想过之前行业的门槛是什么样的,现在行业门槛是什么样的?以前企业对于程序员能力要求没有这么高,甚至十多年前你只要会写个“Hello World”,你都可以入门这个行业,所以以前要入门是完全可以入门的。
②现在也有一些优秀的年轻大牛,他们或许也是自学成才,但是他们一定是具备优秀的学习能力,优秀的自我管理能力(时间管理,静心坚持等方面)以及善于发现问题并总结问题。
如果说你认为你的目标十分明确,能做到第②点所说的几个点,以目前的市场来看,你才真正的适合去自学。
除此之外,对于绝大部分人来说,报班一定是最好的一种快速成长的方式。但是有个问题,现在市场上的培训机构质量参差不齐,如果你没有找准一个好的培训班,完全是浪费精力,时间以及金钱,这个需要自己去甄别选择。
我个人建议线上比线下的性价比更高,线下培训价格基本上没2W是下不来的,线上教育现在比较成熟了,此次疫情期间,学生基本上都感受过线上的学习模式。相比线下而言,线上的优势以我的了解主要是以下几个方面:
①价格:线上的价格基本上是线下的一半;
②老师:相对而言线上教育的师资力量比线下更强大也更加丰富,资源更好协调;
③时间:学习时间相对而言更自由,不用裸辞学习,适合边学边工作,降低生活压力;
④课程:从课程内容来说,确实要比线下讲的更加深入。
应该学哪些技术才能达到企业的要求?(下图总结)
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
rld”,你都可以入门这个行业,所以以前要入门是完全可以入门的。
②现在也有一些优秀的年轻大牛,他们或许也是自学成才,但是他们一定是具备优秀的学习能力,优秀的自我管理能力(时间管理,静心坚持等方面)以及善于发现问题并总结问题。
如果说你认为你的目标十分明确,能做到第②点所说的几个点,以目前的市场来看,你才真正的适合去自学。
除此之外,对于绝大部分人来说,报班一定是最好的一种快速成长的方式。但是有个问题,现在市场上的培训机构质量参差不齐,如果你没有找准一个好的培训班,完全是浪费精力,时间以及金钱,这个需要自己去甄别选择。
我个人建议线上比线下的性价比更高,线下培训价格基本上没2W是下不来的,线上教育现在比较成熟了,此次疫情期间,学生基本上都感受过线上的学习模式。相比线下而言,线上的优势以我的了解主要是以下几个方面:
①价格:线上的价格基本上是线下的一半;
②老师:相对而言线上教育的师资力量比线下更强大也更加丰富,资源更好协调;
③时间:学习时间相对而言更自由,不用裸辞学习,适合边学边工作,降低生活压力;
④课程:从课程内容来说,确实要比线下讲的更加深入。
应该学哪些技术才能达到企业的要求?(下图总结)
[外链图片转存中…(img-fN2Vu9E2-1713551137449)]
[外链图片转存中…(img-YRjaKqUj-1713551137451)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!