一、概念
1、定义:将一个复杂对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示;用户只需指定需要建造的类型就可以得到它们(相同的构建过程创建出不同的产品),不需要知道建造的过程以及细节。
2、类型:创建型
3、适用场景:如果一个对象有非常复杂的内部结构(很多属性);想把复杂对象的创建和使用分离
4、优缺点
- 优点:
- 封装性好,创建和使用分离,将主要的业务逻辑封装在导演类中能够取得较好的稳定性。
- 扩展性好,建造类之间互相独立,在一定程度上解耦,如果有新的需求,再添加一个建造者即可,不用修改之前的代码。
- 缺点:
- 会产生多余的Builder对象;
- 如果产品内部发生变化,建造者需要修改,成本较大
5、和工厂模式的区别
- 建造者模式更注重方法的调用顺序,工厂模式更注重产品;建造者模式可以创建一些复杂的产品,工厂模式都创建的相同的产品;工厂模式只是创建一个产品,而建造者模式不只是创建产品,还知道这些产品是由哪些部件组成的。
- 当创造一个对象需要很多步骤时,适合使用建造者模式,而需要简单地创建整个对象时,适合使用工厂相关的模式
6、类图
Builder
:抽象的建造者,将具体的建造过程交给子类来实现,这样更容易扩展,其中可以分为两大部分,一部分是建造产品,另一个用来返回产品。
ConcreteBuilder
:具体的建造者,用来组件产品和返回产品
Product
:产品类。当产品较为复杂时,产品类可由抽象类与不同的实现组成
Director
:导演类,充当指挥官,持有抽象建造者,负责调用适当的具体建造者来建造自己需要的产品。导演类与产品类没有依赖关系,与导演类直接交互的是建造者类。导演类被用来封装程序中易变的部分,如业务逻辑。
二、Coding
案例类图,Coach
持有抽象建造者,实际建造者继承了抽象建造者并持有一个课程类
//抽象建造者,也可以声明成接口
public abstract class CourseBuilder {
//抽象方法交给子类来实现
public abstract void buildCourseName (String courseName);
public abstract void buildCoursePPT (String coursePPT);
public abstract void buildCourseVideo (String courseVideo);
public abstract void buildCourseArticle (String courseArticle);
public abstract void buildCourseQA (String courseQA);
//build完课程的各种元素就要制作课程
public abstract Course makeCourse();
}
//课程真正的建造者
public class CourseActualBuilder extends CourseBuilder{
//组合到课程实际的builder中
private Course course = new Course();
@Override
public void buildCourseName(String courseName) {
course.setCourseName(courseName);
}
@Override
public void buildCoursePPT(String coursePPT) {
course.setCoursePPT(coursePPT);
}
@Override
public void buildCourseVideo(String courseVideo) {
course.setCourseVideo(courseVideo);
}
@Override
public void buildCourseArticle(String courseArticle) {
course.setCourseArticle(courseArticle);
}
@Override
public void buildCourseQA(String courseQA) {
course.setCourseQA(courseQA);
}
@Override
public Course makeCourse() {
return course;
}
}
//课程类
public class Course {
private String courseName;
private String coursePPT;
private String courseVideo;
private String courseArticle;
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;
}
@Override
public String toString() {
return "Course{" +
"courseName='" + courseName + '\'' +
", coursePPT='" + coursePPT + '\'' +
", courseVideo='" + courseVideo + '\'' +
", courseArticle='" + courseArticle + '\'' +
", courseQA='" + courseQA + '\'' +
'}';
}
}
//Director,课程教练通过讲师提供的各种资料,拼装成一个课程
public class Coach {
//director导演类拥有抽象建造者的接口,来指定具体的建造者是谁,让他来建造产品
private CourseBuilder courseBuilder;
public void setCourseBuilder(CourseBuilder courseBuilder) {
this.courseBuilder = courseBuilder;
}
//调用建造者来为自己创造产品,对外提供makeCourse方法来直接获得产品
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);
return this.courseBuilder.makeCourse();
}
}
public class Test {
public static void main(String[] args) {
//new一个真实的建造者
CourseBuilder courseBuilder = new CourseActualBuilder();
//创建指挥官director类
Coach coach = new Coach();
//把建造者给指挥官
coach.setCourseBuilder(courseBuilder);
Course course = coach.makeCourse("java设计模式", "设计模式PPT", "设计模式视频", "设计模式笔记", "设计模式精讲问答");
System.out.println(course);
}
}
以上例子可以加入多个建造者,当我们的需求很稳定,只需要一个建造者时,可以使用静态内部类的方式,其核心在于使用链式调用,能够实现按需调用。
//如果没有那么多需求,只有一个建造者的情况,可以使用静态内部类的方式
//静态内部类就是建造者
//把具体的实体类和实体类对应的Builder创建在一个类当中,利用链式调用实现
public class Course {
private String courseName;
private String coursePPT;
private String courseVideo;
private String courseArticle;
private String courseQA;
//搞定完Builder类中的细节后,我们需要通过这个Builder返回一个Course
public Course(CourseBuilder courseBuilder) {
this.courseName = courseBuilder.courseName;
this.coursePPT = courseBuilder.coursePPT;
this.courseVideo = courseBuilder.courseVideo;
this.courseArticle = courseBuilder.courseArticle;
this.courseQA = courseBuilder.courseQA;
}
@Override
public String toString() {
return "Course{" +
"courseName='" + courseName + '\'' +
", coursePPT='" + coursePPT + '\'' +
", courseVideo='" + courseVideo + '\'' +
", courseArticle='" + courseArticle + '\'' +
", courseQA='" + courseQA + '\'' +
'}';
}
//静态内部类就是建造者
public static class CourseBuilder{
private String courseName;
private String coursePPT;
private String courseVideo;
private String courseArticle;
private String courseQA;
//这个写法的核心在于链式调用,这里返回的是本身return this
// 它本身又持有各种build方法,这样就可以继续调用其他的build方法
public CourseBuilder buildCourseName(String courseName){
this.courseName = courseName;
return this;
}
public CourseBuilder buildCoursePPT(String coursePPT){
this.coursePPT = coursePPT;
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;
}
//最终返回产品
public Course build(){
return new Course(this);
}
}
}
public class Test {
public static void main(String[] args) {
//链式调用,调完courseName返回值还是courseBuilder,可以实现按需调用
Course course = new Course.CourseBuilder().buildCourseName("java精讲").buildCoursePPT("java精讲PPT").buildCourseVideo("精讲视频").buildCourseArticle("java精讲手记").buildCourseQA("java精讲问答").build();
System.out.println(course);
}
}
CourseBuilder`作为课程的建造着,应用层只需要与这个具体的建造者进行交互,设置产品的具体属性,最后调用build方法,返回具体的实体类即可。
三、实际应用
jdk中的StringBuilder
,比如append
方法
StringBuffer
同理,只不过增加了同步方法
再如Spring
中的BeanDefinitionBuilder
以及Mybatis
中的SqlSessionFactoryBuilder
等也都是使用了建造者模式。