建造者模式应用的非常广泛,我们通过coding实战一起来了解一下,建造者模式也是创建型,我们讲的各种工厂也是创建型,当创建一个对象需要很多步骤时,适合使用建造者模式,而当需要一个简单的方法,就可以简单的创建一个对象时,适合使用工厂相关模式,这么说还不如直接coding的好,现在有一个业务场景,这个业务场景是说,建造一个网站的课程,但是建造者的应用场景有很多,例如说我们去盖房子,建造一个房子,例如说我们要组装主板,CPU,硬盘,内存等等,现在我们的业务场景就是说,建造一个视频课程,例如我们的JAVA设计模式精讲

和CourseBuilder进行一个组合,一个教练里面包含一个课程的,建造者他们是一比一的关系,然后持有的是一个抽象的建造者,下边你是实际的建造者,并且实际的建造者中持有一个课程类,UML类图还是非常简单清晰明了的,这个就是一个标准的建造者,UML类图,那实际的建造者就继承了抽象类,实现里面的抽象方法,那现在我们创建一个测试类

主要关注Test,其他四个类关系没有变,Test他和抽象的标准,和具体的课程呢,都没有关系,但是他和教练有关系,他来创建这个指挥官,然后指挥官通过组合的方式,使用课程Builder这个抽象类,实际使用的是CourseActualBuilder,来创建这个Course,然后应用层通过这个教练拿到了具体的课程类,那我们现在想象一下,对于这个抽象类,有一个继承他的实现类,而Test创建具体的Builder,也就是说我可以有很多的Builder,每个Builder他的特点他不一样,例如我们还有一个前端课程的builder,里面还要builder一个前端资源,这个呢为了加以区分,我们还可以把它命名为后端课程的builder,所以根据实际课程的不同,我们在应用层可以选择不同的Builder,来传给课程经理,然后他拿到应用层,传给他的具体Builder,来创建整个课程,也就是说把注入Builder的职责呢,现在是交给Test了,那当然还有一种方式,例如这个教学就是一个后端课程的教学,他完全不需要前端图片的各种素材资源,那么我们可以把后端课程的builder,注入到后端课程经理当中,这样应用层都不用关心builder,也就是说这个箭头直接干掉,应用层只和具体的教学教练有关,也就是说应用层只和指挥官进行交互,这条线直接被砍掉,他们两之间也不会建立关系,抽象类或接口builder都是OK的,只不过我们这里没有一个具体的实现方法,所以使用抽象类还是接口,效果都是一样的,那这里我们再演进一下,也就是这个指挥官教练,不是必须的,我们在演进的过程中,我们可以使用链式调用,我们在后续的coding当中,也会讲一下在源码框架中,一些链式调用的体现,我们在这里面创建一个V2版本
package com.learn.design.pattern.creational.builder;/*** 首先我们创建这个类Course* 还是这个课程类* 这个课程有几个属性* * * @author Leon.Sun**/
public class Course {/*** 课程的名字* 如果想在网站上上线一个课程的话* 名字是必须的* */private String courseName;/*** 还有课程所需要的PPT* */private String coursePPT;/*** 还有课程所需要的Video* 我们这里都先理解为String类型* */private String courseVideo;/*** 课程的手记* 四个元素有了之后呢* */private String courseArticle;//question & answer/*** 这里的QA表示问题和答案* */private String courseQA;public String getCourseName() {return courseName;}public void setCourseName(String courseName) {this.courseName = courseName;}public String getCoursePPT() {return coursePPT;}public void setCoursePPT(String coursePPT) {this.coursePPT = coursePPT;}public String getCourseVideo() {return courseVideo;}public void setCourseVideo(String courseVideo) {this.courseVideo = courseVideo;}public String getCourseArticle() {return courseArticle;}public void setCourseArticle(String courseArticle) {this.courseArticle = courseArticle;}public String getCourseQA() {return courseQA;}public void setCourseQA(String courseQA) {this.courseQA = courseQA;}@Overridepublic String toString() {return "Course{" +"courseName='" + courseName + '\'' +", coursePPT='" + coursePPT + '\'' +", courseVideo='" + courseVideo + '\'' +", courseArticle='" + courseArticle + '\'' +", courseQA='" + courseQA + '\'' +'}';}
}
package com.learn.design.pattern.creational.builder;/*** 课程的建造者* 如果抽象建造者都是抽象方法的话* 我们声明成接口也是OK的* 只不过我们这里面先用抽象类* 那里面一共几个属性呢* 一共五个属性* 然后开始写他的build方法* 抽象方法写完了* 抽象方法就是交给子类来实现的* 接下里我们要写一个实现Builder的一个子类* * * @author Leon.Sun**/
public abstract class CourseBuilder {/*** 这里面传入一个courseName* 这个是课程的建造者* 下面去build课程的各种元素* 同理其他的字段也是一样的* * * @param courseName*/public abstract void buildCourseName(String courseName);public abstract void buildCoursePPT(String coursePPT);public abstract void buildCourseVideo(String courseVideo);/*** 课程的手记* * @param courseArticle*/public abstract void buildCourseArticle(String courseArticle);/*** 课程的问答* * @param courseQA*/public abstract void buildCourseQA(String courseQA);/*** 我们还要写一个抽象方法* 返回一个Course* 叫做制作过程* 这么一个抽象的build就写完了* * * @return*/public abstract Course makeCourse();
}
package com.learn.design.pattern.creational.builder;/*** 课程真正的build* 继承CourseBuilder这个抽象类* 实现里面的方法* 这里面我们简化一下* 合到实际的build当中* 下面的实现也非常的简单* * * @author Leon.Sun**/
public class CourseActualBuilder extends CourseBuilder {private Course course = new Course();@Overridepublic void buildCourseName(String courseName) {/*** 直接把courseName传进来* 下边也都是同理* * 而这个Course是在Builder当中创建的* 也就是说private Course course = new Course();在这个位置* 所以调用了setCourseName* 现在里面的属性都是空的* 然后courseName就赋值成功* 其他的属性也是一样的* * */course.setCourseName(courseName);}@Overridepublic void buildCoursePPT(String coursePPT) {course.setCoursePPT(coursePPT);}@Overridepublic void buildCourseVideo(String courseVideo) {course.setCourseVideo(courseVideo);}@Overridepublic void buildCourseArticle(String courseArticle) {course.setCourseArticle(courseArticle);}@Overridepublic void buildCourseQA(String courseQA) {course.setCourseQA(courseQA);}/*** 我们把断点打到makeCourse这里面* 可以看到course其他的属性都赋值成功了* 然后把这个course进行返回* * */@Overridepublic Course makeCourse() {/*** 上面的属性都添加完之后呢* 我们这里面直接返回一个Course就OK了* 就完成了课程的一个制作* 这个时候我们要引入一个教练类* 教练起到什么作用呢* 很简单* 讲师和网站合作的时候* 网站会有工作人员和讲师对接* 那这个人就可以称之为课程教练* 或者教学经理* 他主要的职责就是和讲师对接* 这里面我们来想一下* 公司的老板在下达课程任务的时候呢* 会直接和课程教练进行沟通* 然后课程教练和对应的讲师进行对接* 然后来共同制作这个课程* 简单的理解* 可以认为课程教练充当一个指挥官* 讲师提交课程的名字* 提交课程的手记* 提交课程的视频* 等等* 然后课程教练通过讲师提供的各种资料* 来拼装成这么一个课程* 后面我们也会演示一下构造者模式* 也就是说这个课程教练不是必须的* 不过我们的建造者也要演进两个版本* 这样也是为了更好地理解* 接下来我们就写一下* * */return course;}}
package com.learn.design.pattern.creational.builder;/*** * @author Leon.Sun**/
public class Coach {/*** 这个教练肯定是含有我们的课程Builder* */private CourseBuilder courseBuilder;/*** 这个Builder我们通过set注入的方式注入进来* * * @param courseBuilder*/public void setCourseBuilder(CourseBuilder courseBuilder) {this.courseBuilder = courseBuilder;}/*** 在教练这个类里面肯定有一个行为* 返回值是课程* 里面要传入课程的各种属性* 首先是课程的名字* 还有课程的PPT* 课程的视频* 课程的手记* 还有课程的问答* 一旦讲师提交了这些给课程经理制造课程* 在制造这些课程的时候* 需要调用课程的Builder* * 在这里面打一个断点* 首先传入的值是下面看到的值* 然后里面调用的是courseBuilder* courseBuilder是private CourseBuilder courseBuilder这个对象* 之前new完之后通过set方法注入进来的* 然后他调用了buildCourseName* 进入到抽象类里面* 我们Ctrl + T进入到具体实现类* * * @param courseName* @param coursePPT* @param courseVideo* @param courseArticle* @param courseQA* @return*/public Course makeCourse(String courseName,String coursePPT,String courseVideo,String courseArticle,String courseQA){/*** 把这些属性挨个传进来* */this.courseBuilder.buildCourseName(courseName);this.courseBuilder.buildCoursePPT(coursePPT);this.courseBuilder.buildCourseVideo(courseVideo);this.courseBuilder.buildCourseArticle(courseArticle);this.courseBuilder.buildCourseQA(courseQA);/*** 就会返回Builder里面声明的Course* * 这个时候就直接返回builder创建的course* 这么一个对象* 返回值类型是课程类型* * */return this.courseBuilder.makeCourse();}
}
package com.learn.design.pattern.creational.builder;/*** * @author Leon.Sun**/
public class Test {public static void main(String[] args) {/*** 抽象的父类引用创建一个子类的实现* * 首先创建一个Builder没有什么好说的* */CourseBuilder courseBuilder = new CourseActualBuilder();/*** 然后new一个教练出来* * 然后创建一个教练* */Coach coach = new Coach();/*** 把这个Builder注入进去* 那现在就比较简单* * 然后把这个builder放到教练里面* */coach.setCourseBuilder(courseBuilder);/*** 调用一下* 返回值是Course* 调用教学经理的makeCourse* 里面传入参数* 首先是课程名称"Java设计模式精讲"* 然后第二个是PPT"Java设计模式精讲PPT"* 第三个参数视频* 第四个参数手记* 第五个参数问答* 也就是说现在创建这个课程* 是由指挥官教学教练来创建课程* 拿到讲师提交的各种资料* 通过注入一个课程Builder* 这种方式呢* 来完成课程的健壮* * 然后看makeCourse关键方法* * */Course course = coach.makeCourse("Java设计模式精讲","Java设计模式精讲PPT","Java设计模式精讲视频","Java设计模式精讲手记","Java设计模式精讲问答");/*** 然后输出这个课程* * 这个时候就开始输出这个course* 整个课程就输出出来了* 和预期保持一致* 我们在再看一下UML类图* */System.out.println(course);}
}

这个类图就比刚刚那个类图简单许多,作为课程实体类的建造者,而应用层只需要控制和哪个建造者进行交互,然后设置他具体的属性,最后调用build这个方法,返回具体的实体类
package com.learn.design.pattern.creational.builder.v2;/*** v2版本中直接创建一个课程类* 这里就需要使用静态的内部类* 而这个内部类不是一个建造者* 首先把这些属性拿过来* 然后重写一下toString方法* 为一会测试使用* 这种建造者模式使用的非常广* 就是把具体的实体类和builder放在一个类当中* * * @author Leon.Sun**/
public class Course {/*** 这里面还是有这五个属性* */private String courseName;private String coursePPT;private String courseVideo;private String courseArticle;//question & answerprivate String courseQA;/*** 这个Course需要一个构造器* 里面的参数改成courseBuilder* 而这个courseBuilder是静态内部类* CourseBuilder这个类创建的对象* * * @param courseBuilder*/public Course(CourseBuilder courseBuilder) {/*** 所以我们再实现一下他的构造器* 这样Course这个类的所有属性就通过Builder来构建成功了* 我们现在再写一个测试类* * 通过build里面获取的属性* 这个时候的this就是Course了* * */this.courseName = courseBuilder.courseName;this.coursePPT = courseBuilder.coursePPT;this.courseVideo = courseBuilder.courseVideo;this.courseArticle = courseBuilder.courseArticle;/*** 这里courseQA是空所以为空* this三个属性都从courseBuilder获取成功* 赋值到Course对象当中* * */this.courseQA = courseBuilder.courseQA;}@Overridepublic String toString() {return "Course{" +"courseName='" + courseName + '\'' +", coursePPT='" + coursePPT + '\'' +", courseVideo='" + courseVideo + '\'' +", courseArticle='" + courseArticle + '\'' +", courseQA='" + courseQA + '\'' +'}';}/*** 这么一个静态内部类* * * @author Leon.Sun**/public static class CourseBuilder{private String courseName;private String coursePPT;private String courseVideo;private String courseArticle;//question & answerprivate String courseQA;/*** 直接写一个方法buildCourseName* 传一个String的buildCourseName* * 首先进入buildCourseName* * @param courseName* @return*/public CourseBuilder buildCourseName(String courseName){/*** 给build中的courseName赋值* 演进版在于链式调用* 注意这里返回的是本身CourseBuilder* * 首先这个build的this* 是Course下面的$的CourseBuilder* 里面的属性都是空* 通过这种方式已经赋值了name了* 也就是把这个this本身返回回去* * */this.courseName = courseName;/*** return之后还可以调用其他的的方法* 因为这个build方法返回本身* 而它本身又持有各种方法* 一会写测试的时候一起来体会链式调用* 非常简单* 我们再copy一些方法过来* * */return this;}/*** 返回值统一成CourseBuilder* * 然后在PPT中再打个断点* * * @param coursePPT* @return*/public CourseBuilder buildCoursePPT(String coursePPT) {/*** 首先这个this已经通过上面赋值成功了* 然后在这里面又把PPT赋值上* * */this.coursePPT = coursePPT;/*** 然后又把this返回回去* */return this;}public CourseBuilder buildCourseVideo(String courseVideo) {this.courseVideo = courseVideo;return this;}public CourseBuilder buildCourseArticle(String courseArticle) {this.courseArticle = courseArticle;return this;}public CourseBuilder buildCourseQA(String courseQA) {this.courseQA = courseQA;return this;}/*** 我们直接写个方法* * 最后他又调用一下build方法* * @return*/public Course build(){/*** 传入一个类* 把它自己传入进来* * 这个时候this已经通过我们的应用层设置了是三个属性* 都设置成功了* 还有两个没有设置所以为空* 当然我们的实际建造者可以写一个默认值* 然后调用Course构造器* */return new Course(this);}}
}
package com.learn.design.pattern.creational.builder.v2;import com.google.common.collect.ImmutableSet;import java.util.Set;/*** 对于V2版本我们debug一下* 我们打个断点* * * @author Leon.Sun**/
public class Test {public static void main(String[] args) {/*** 直接创建一个课程* 直接调用CourseBuilder对象* 很简单* 现在这种方式是链式调用* 所以直接调用buildCourseName"Java设计模式精讲"* 注意他的返回值是CourseBuilder* 我可以继续来点* build什么呢* 比如他的PPT肯定是要的* buildCoursePPT* 所以把这个拿过来* 他的视频也是要的* buildCourseVideo* 这些都是必须的* 他的手记不是必须的* 所以我可以不必build他的Article* 最后的返回值是Course* 还要调用一下他的build方法* 这个时候课程才创建成功* * */Course course = new Course.CourseBuilder().buildCourseName("Java设计模式精讲").buildCoursePPT("Java设计模式精讲PPT").buildCourseVideo("Java设计模式精讲视频").build();/*** 我们直接输出run一下* 可以看到这里面都是输出成功* courseArticle和courseQA是一个空值* 也就是这个可以按需调用* 这就是演进版本的最大优点* 这里又五个属性* 如果属性更多的话* 很容易写串* 例如我们这里都是String类型* 例如我们赋值的位置不对* 或者把对象赋值错了* 这个在实际的开发过程中* 也可能因为马虎而发生* 而通过演进版的方式* 我们build什么属性* 是非常明确的* 当然呢如果这里面就是写错了* 那也没有办法* 这个肯定是bug* 只不过通过这两种方式的对象* 链式调用更方便点* 但是最后一定要调用build方法* 返回值才是具体的课程* 再看一下V2版本的类图* * V2的方式在实际的应用中写的也是比较多的* 首先它把具体的实体类和具体实体类的builder* 写在一个类里* 包括以后维护什么的* 都会比较方便* 希望通过两个版本的coding* 建造者模式有一个深刻的理解* 并且掌握牢固* 可以用到我们的实际项目当中* * * */System.out.println(course);Set<String> set = ImmutableSet.<String>builder().add("a").add("b").build();//        System.out.println(set);}
}

建造者模式 coding相关推荐

  1. Python设计模式-建造者模式

    Python设计模式-建造者模式 代码基于3.5.2,代码如下; #coding:utf-8 #建造者模式 class Burger():name = ""price = 0.0d ...

  2. 设计模式系列-建造者模式

    快乐技术沙龙即将一周岁了,最近它又多了个妹妹叫<嗨皮吧>,春哥(秦春林)还是很给力啊!一连搞两个组织(社团 (∩_∩)),那么还是主要介绍一下妹妹嗨皮吧好啦,说起嗨皮吧还真是有很多吸引人的 ...

  3. 重识设计模式-建造者模式(Builder Pattern)

    本文已同步发表到我的技术微信公众号,扫一扫文章底部的二维码或在微信搜索 "程序员驿站"即可关注,不定期更新优质技术文章.同时,也欢迎加入QQ技术群(群号:650306310)一起交 ...

  4. Myabtis源码分析五-Mybatis配置加载完全图解,建造者模式的使用,涵盖Java各种技术栈

    private SqlSessionFactory sqlSessionFactory; @Before public void init() throws IOException { //----- ...

  5. java设计模式之建造者模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  6. GOF23设计模式(创建型模式)建造者模式

    使用场景: 我们要建造一个复杂的产品,比如生产一辆汽车.一部手机,这都是由很多零部件组成的,这时候就需要用到我们的建造者模式,将每个零部件分别生产,然后再装配~~ 以下,我将以一个手机的生产过程为实例 ...

  7. 设计模式 之美 -- 建造者模式

    文章目录 1. 解决问题 2. 应用场景 3. 实现 C语言实现 C++实现 4. 缺点 1. 解决问题 描述如下场景: 类的数据成员很多(8个以上),当我们进行初始化的时候放在初始化列表中,影响类的 ...

  8. 设计模式之建造者模式(生成器模式、Builder)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式包括:1.FactoryMethod(工厂方法模式):2.Abstract Factory(抽象工厂模式):3.Sin ...

  9. 动态表单构建器——建造者模式

    在编写一个弹出框时,它可以包含确定按钮,取消按钮,标题栏,关闭按钮,最小化按钮,内容,最大化按钮等内容,但这些内容在不同的需求下又不是必须存在的,不同的需求需要对这些组件自由组合,显然每次组合都要重复 ...

最新文章

  1. 清华大学副校长杨斌在“双创”教育论坛暨经验研讨会开幕式上致辞:创新创业教育与大学未来...
  2. 沈石溪事件持续发酵 韩国将严查体育界暴力事件
  3. Java源文件声明规则
  4. 如何关闭window10自动更新
  5. JavaScript Promise查缺补漏
  6. 计算机的任务管理器作用,电脑技术:如何妙用任务管理器
  7. 计算机网络工程安装,一种计算机网络工程用施工平台的制作方法
  8. 万能启动利器FbinstTool引导工具教程
  9. python图案堆积_Python数据可视化,我是如何做出泡泡堆积关联图
  10. 从IRQ到IRQL(PIC版)
  11. 即将开幕!阿里云飞天技术峰会邀您一同探秘云原生最佳实践
  12. 投影幕布尺寸计算器_投影安装高质量,全靠这个计算器
  13. 数据结构-图的课程设计
  14. 5-1 厘米换算英尺英寸 (15分)
  15. leetcode打家劫社简单实现--python
  16. 039.简单的文本编辑器
  17. 专业修图工具:Affinity Photo for mac
  18. 2022 前端常用的开发工具、组件库等等~持续整理,待你分享~
  19. 6-Ubuntu与Windows不能相互复制
  20. halt ,poweroff和shutdown 的区别

热门文章

  1. bootloader学习笔记
  2. 颜色空间,图像格式,彩色转灰度函数
  3. 手动建立Mysql表实体类技巧
  4. C#和JS交互 WebBrowser实例
  5. python学习笔记之常用模块用法分析
  6. Web服务(Apache、Nginx、Tomcat、Jetty)与应用(LAMP、CMS-WordPressGhost、Jenkins、Gitlab)
  7. 工作中最常用的Excel函数公式大全
  8. JAVA Collection笔记(2012/9/19)
  9. flashcom网址收集
  10. java websocket netty_基于netty实现的websocket