一. 定义与类型
定义:将一个复杂对象的构建与它的表示分离,使用同样的构建过程可以创建不同的表示
用户只需制定需要建造的类型就可以得到它们,建造过程以及细节不需要知道
类型:创建型
建造者模式与工厂模式比较相近,它们的区别在于,
建造者模式注重方法的调用顺序,工厂模式注重创建产品
它们的创建力度不同,建造者模式可以创建较为复杂产品,有各种复杂的部件,而工厂模式创建出来的产品都是一个样子
工厂模式关注的只要把这个产品创建出来就行了,建造者模式不仅要把产品创建出来,还要知道这个产品有哪些部件组成
二. 适用场景
如果一个对象有非常复杂的内部结构(很多熟悉),想把复杂对象的创建和使用分离
三. 优缺点
优点:
封装性好,创建和使用分离
扩展性好,建造类之间独立,一定程度上解耦
缺点:
产生多余的Builder对象
产品内部发生变化,建造者都要修改,成本较大
四. Coding
创建一个抽象的课程建造类:
/*** @program: designModel
* @description:
*@author: YuKai Fan
* @create: 2018-12-03 16:48
**/
public abstract classCourseBuilder {public abstract voidbuildCourseName(String courseName);public abstract voidbuildCoursePPT(String coursePPT);public abstract voidbuildCourseVideo(String courseVideo);public abstract voidbuildCourseArticle(String courseArticle);public abstract voidbuildCourseQA(String courseQA);//上面的都属于课程的组件,这个方法时课程的建造
public abstractCourse makeCourse();
}
创建一个实际的建造类:
/*** @program: designModel
* @description:
*@author: YuKai Fan
* @create: 2018-12-03 16:50
**/
public class CourseActualBuilder extendsCourseBuilder{private Course course = newCourse();public voidbuildCourseName(String courseName) {
course.setCourseName(courseName);
}public voidbuildCoursePPT(String coursePPT) {
course.setCoursePPT(coursePPT);
}public voidbuildCourseVideo(String courseVideo) {
course.setCourseVideo(courseVideo);
}public voidbuildCourseArticle(String courseArticle) {
course.setCourseArticle(courseArticle);
}public voidbuildCourseQA(String courseQA) {
course.setCourseQA(courseQA);
}publicCourse makeCourse() {returncourse;
}
}
创建建造者实体类:
/*** @program: designModel
* @description:
*@author: YuKai Fan
* @create: 2018-12-03 16:52
**/
public classCoach {privateCourseBuilder courseBuilder;//通过set注入,传入的课程建造的值
public voidsetCourseBuilder(CourseBuilder courseBuilder) {this.courseBuilder =courseBuilder;
}//课程建造方法
publicCourse makeCourse(String courseName,
String coursePPT,
String courseVideo,
String courseArticle,
String courseQA) {this.courseBuilder.buildCourseName(courseName);this.courseBuilder.buildCoursePPT(coursePPT);this.courseBuilder.buildCourseArticle(courseArticle);this.courseBuilder.buildCourseVideo(courseVideo);this.courseBuilder.buildCourseQA(courseQA);return this.courseBuilder.makeCourse();
}
}
应用层:
/*** @program: designModel
* @description:
*@author: YuKai Fan
* @create: 2018-12-03 16:56
**/
public classTest {public static voidmain(String[] args) {
CourseBuilder courseBuilder= newCourseActualBuilder();
Coach coach= newCoach();
coach.setCourseBuilder(courseBuilder);
Course course= coach.makeCourse("Java设计模式","Java设计模式PPT","Java设计模式视频","Java设计模式手记","Java设计模式问答");
System.out.println(course);
}
}
UML类图:
从上方的UML类图与coding可以看出,建造者模式,将课程的表示与建造分离开了,test只需要传入相应的课程类型就可以创建课程。
test与抽象的课程建造类,课程类都没有关系,但是与coach指挥官有关,创建指挥管通过组合的方式使用coursebuilder这个抽象类,拿到具体的课程类。
可以有很多的builder比如,前端builder和后端builder,test可以选择不同的builder,传到对应的coach,然后coach通过拿到不同的builder来创建不同的课程,也就是说,把这个注入的职责交给应用层。
还有一种,如果只有一个后端课程,没有其他课程。那就可以把,后端的课程的builder默认注入到后端课程coach中,应用层不需要与courseActualBuilder有交互了,只和具体的coach有关。
建造者升级(演进),这个coach完全可以不需要,也就是链式调用
建造者模式V2:使用静态内部类,把具体的实体类与具体的builder类,创建在一个类中
/*** @program: designModel
* @description:
*@author: YuKai Fan
* @create: 2018-12-03 17:02
**/
public classCourse {privateString courseName;privateString coursePPT;privateString courseVideo;privateString courseArticle;//question & answer
privateString courseQA;publicCourse(CourseBuilder courseBuilder) {this.courseName =courseBuilder.courseName;this.coursePPT =courseBuilder.coursePPT;this.courseVideo =courseBuilder.courseVideo;this.courseArticle =courseBuilder.courseArticle;this.courseQA =courseBuilder.courseQA;
}//内部类
public static classCourseBuilder{privateString courseName;privateString coursePPT;privateString courseVideo;privateString courseArticle;//question & answer
privateString courseQA;publicCourseBuilder buildCourseName(String courseName){this.courseName =courseName;return this;
}publicCourseBuilder buildCoursePPT(String coursePPT) {this.coursePPT =coursePPT;return this;
}publicCourseBuilder buildCourseVideo(String courseVideo) {this.courseVideo =courseVideo;return this;
}publicCourseBuilder buildCourseArticle(String courseArticle) {this.courseArticle =courseArticle;return this;
}publicCourseBuilder buildCourseQA(String courseQA) {this.courseQA =courseQA;return this;
}publicCourse build() {return new Course(this);
}
}
@OverridepublicString toString() {return "Course{" +
"courseName='" + courseName + '\'' +
", coursePPT='" + coursePPT + '\'' +
", courseVideo='" + courseVideo + '\'' +
", courseArticle='" + courseArticle + '\'' +
", courseQA='" + courseQA + '\'' +
'}';
}
}
test:
/*** @program: designModel
* @description:
*@author: YuKai Fan
* @create: 2018-12-03 17:08
**/
public classTest {public static voidmain(String[] args) {
Course course= new Course.CourseBuilder().buildCourseName("Java设计模式").buildCoursePPT("Java设计模式PPT").buildCourseVideo("Java设计模式视频").buildCourseQA("Java设计模式问答").build();
System.out.println(course);
}
}
UML类图:
这种方式,在实际应用当中用的比较多,以后的维护都会比较方便。
无论那种方式,建造者模式,将产品的构造,组件都分离开。从上面的例子可以看出,course的创建(具体过程),启动course的创建(coach来创建),创建哪种course(test应用层)都分的清清楚楚,即模块化,达到了模块分离的效果。这样维护和扩展都很方便
五. 源码分析
使用最多最常用的StringBuilder,StringBuffer它们的append方法。就是使用了建造者模式,也是使用的链式调用.
CacheBuilder方法,也是典型的建造者模式
Spring中的BeanDefinitionBuilder,Mybatis中的SqlSessionFactoryBuilder