1 基本概念

1.0 为啥要生成器模式?

系统中一些复杂对象,拥有多个组成部分,如汽车包括车轮、方向盘、发送机等各部件。而大多数用户,无须知道这些部件的装配细节,也几乎不会使用单独某部件,而是使用一辆完整汽车!

这时就可通过建造者模式对其进行设计描述,建造者模式可将部件和其组装过程分开,一步一步创建一个复杂对象。用户只需指定复杂对象的类型就可得到该对象,而无须知其内部构造细节。

软件开发也存在大量类似汽车复杂对象,拥有一系列属性,这些复杂对象还可能存在一些限制条件,如:

  • 某些属性没有赋值,则复杂对象不能作为一个完整产品使用
  • 有些属性的赋值须按顺序,一个属性没赋值前,另一个属性可能无法赋值

复杂对象相当于一辆有待建造的汽车,而对象的属性相当于汽车部件,建造产品过程就相当于组合部件过程。组合部件过程很复杂,因此,这些部件的组合过程往往被“外部化”到一个称作建造者的对象,建造者返还给客户端的是一个建造完毕的完整产品对象,而用户不关心该对象所包含的属性及它们组装方式,这就是建造者模式。

1.1 定义

① 维基百科定义

生成器模式(Builder Pattern)是一种设计模式,又名:建造模式、Builder模式或构建者模式,是一种对象构建模式。它可将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。

② 简单理解

将一个复杂对象的构建与它的表示分离,使同样构建过程,可创建不同的表示。

用户只需指定需要建造的类型就可以得到它们,建造过程及细节不需要知道。

③ 通用流程

先创建一个初始对象,然后逐渐添加新东西,最后调用 build() 方法完成构建。

1.2 类型

创建型

2 适用场景

  • 当创建复杂对象的算法应该独立于该对象的组成部分及它们的装配方式时
  • 当构造过程必须允许被构造的对象有不同的表示时
  • 一个对象有非常复杂的内部结构(很多属性)
  • 想把复杂对象的创建和使用分离

3 优点

  • 封装性好,创建和使用分离
  • 扩展性好、建造类之间独立、一定程度上解耦

4 缺点

  • 产生多余的Builder对象
  • 产品内部发生变化,建造者都要修改,成本较大,所以需精心设计

5 与其他设计模式的区别

5.1 V.S 工厂模式

工厂模式特点

  • 注重方法调用顺序
  • 创建复杂的作品,有各种复杂的部件组成
  • 不止要创建出来,还要知道产品有哪些部件组成

生成器特点

  • 注重创建产品,不关心顺序
  • 创建出来的都一个样
  • 只要创建出来对象即可

6 实战

课程类:

package com.javaedge.design.pattern.creational.builder.pre;

import lombok.Data;
import lombok.ToString;

/**
 * 课程类
 *
 * @author JavaEdge
 * @date 2018/11/9
 */
@Data
@ToString
public class Course {

    /**
     * 课程名称
     */
    private String courseName;

    /**
     * 课程PPT
     */
    private String coursePPT;

    /**
     * 课程视频
     */
    private String courseVideo;

    /**
     * 课程文档
     */
    private String courseArticle;

    /**
     * 课程QA
     */
    private String courseQA;
}

课程建造者:

package com.javaedge.design.pattern.creational.builder.pre;

/**
 * 课程建造者
 *
 * @author JavaEdge
 * @date 2018/11/9
 */
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);

    public abstract Course makeCourse();
}

课程真正建造:

package com.javaedge.design.pattern.creational.builder.pre;

/**
 * @author JavaEdge
 * @date 2018/11/9
 */
public class CourseActualBuilder extends CourseBuilder {

    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;
    }
}

课程教练:

package com.javaedge.design.pattern.creational.builder.pre;

/**
 * @author JavaEdge
 * @date 2018/11/9
 */
public class Coach {

    private CourseBuilder courseBuilder;

    public void setCourseBuilder(CourseBuilder courseBuilder) {
        this.courseBuilder = courseBuilder;
    }

    public Course makeCourse(String courseName, String coursePPT,
                             String courseVideo, String courseArticle,
                             String courseQA) {
        this.courseBuilder.buildCourseName(courseName);
        this.courseBuilder.buildCourseArticle(courseArticle);
        this.courseBuilder.buildCoursePPT(coursePPT);
        this.courseBuilder.buildCourseQA(courseQA);
        this.courseBuilder.buildCourseVideo(courseVideo);
        return this.courseBuilder.makeCourse();
    }
}

UML:

Java的生成器模式(又名建造者模式),你真的会了吗_Java

测试类:

package com.javaedge.design.pattern.creational.builder.pre;

/**
 * 测试类
 * 
 * @author JavaEdge
 */
public class Test {
    public static void main(String[] args) {

        CourseBuilder courseBuilder = new CourseActualBuilder();
        Coach coach = new Coach();
        coach.setCourseBuilder(courseBuilder);

        Course course = coach.makeCourse("Java 设计模式",
                "Java 设计模式PPT",
                "Java 设计模式视频",
                "Java 设计模式博客",
                "Java 设计模式解疑");
        System.out.println(course);
    }
}

7 开源框架实例

7.1 StringBuilder

几乎都是返回一个自身实例:

Java的生成器模式(又名建造者模式),你真的会了吗_Java_02

Java的生成器模式(又名建造者模式),你真的会了吗_Java_03

7.2 Guava不可变集合类

Java的生成器模式(又名建造者模式),你真的会了吗_Java_04

建造者内部类

Java的生成器模式(又名建造者模式),你真的会了吗_Java_05

和之前同理,必存在一个 build 方法:

Java的生成器模式(又名建造者模式),你真的会了吗_Java_06

7.3 Mybatis - SqlSessionFactoryBuilder

入参为一个配置,传给默认的 session 工厂进行构造:

Java的生成器模式(又名建造者模式),你真的会了吗_Java_07

解析 mybatis 的 xml 文件:

Java的生成器模式(又名建造者模式),你真的会了吗_Java_08

Java的生成器模式(又名建造者模式),你真的会了吗_Java_09

Java的生成器模式(又名建造者模式),你真的会了吗_Java_10