设计模式(12):建造者模式

一、概念

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方法
StringBuilder.apped()
StringBuffer同理,只不过增加了同步方法
StringBuffer.apped()
再如Spring中的BeanDefinitionBuilder以及Mybatis中的SqlSessionFactoryBuilder等也都是使用了建造者模式。

发布了43 篇原创文章 · 获赞 6 · 访问量 3907

猜你喜欢

转载自blog.csdn.net/weixin_44424668/article/details/103269603