设计模式-建造者模式(Builder Pattern)

建造者模式

定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
创建者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象。

类型
创建型。

适用场景

  1. 需要生成的产品对象有复杂的内部结构,这些产品对象具备共性。
  2. 隔离复杂对象的创建和使用,并使得相同的构建过程可以创建不同的产品。

建造者模式与抽象工厂模式的比较

  • 与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
  • 在抽象工厂模式中,应用层实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,应用层可以不直接调用建造者类的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象。
  • 如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车

设计模式-抽象工厂模式(Abstract Factory Pattern)

优点

  1. 使用建造者模式可以使应用层不必知道产品内部组成的细节。
  2. 具体的建造者类之间是相互独立的,这有利于系统的扩展。
  3. 具体的建造者相互独立,因此可以对建造的过程逐步细化,而不会对其他模块产生任何影响。

缺点

  1. 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
  2. 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。

例子
Course类(课程类),一个产品类。

package com.kaven.design.pattern.creational.builder;

public class Course {

    private String courseName;
    private String coursePPT;
    private String courseVideo;
    private String courseArticle;

    //question and answer
    private String courseQA;

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }

    public void setCoursePPT(String coursePPT) {
        this.coursePPT = coursePPT;
    }

    public void setCourseVideo(String courseVideo) {
        this.courseVideo = courseVideo;
    }

    public void setCourseArticle(String courseArticle) {
        this.courseArticle = courseArticle;
    }

    public void setCourseQA(String courseQA) {
        this.courseQA = courseQA;
    }

    @Override
    public String toString() {
        return "Course{" +
                "courseName='" + courseName + '\'' +
                ", coursePPT='" + coursePPT + '\'' +
                ", courseVideo='" + courseVideo + '\'' +
                ", courseArticle='" + courseArticle + '\'' +
                ", courseQA='" + courseQA + '\'' +
                '}';
    }
}

CourseBuilder类(抽象类,也可以定义为接口),是课程(产品)的抽象建造者类,定义创建课程实例的各种接口。

package com.kaven.design.pattern.creational.builder;

public abstract class CourseBuilder {

    public abstract void builderCourseName(String courseName);
    public abstract void builderCoursePPT(String coursePPT);
    public abstract void builderCourseVideo(String courseVideo);
    public abstract void builderCourseArticle(String courseArticle);
    public abstract void builderCourseQA(String courseQA);

    public abstract Course makeCourse();
}

CourseActualBuilder类,是课程(产品)真正的创建者类。

package com.kaven.design.pattern.creational.builder;

public class CourseActualBuilder extends CourseBuilder {

    private Course course = new Course();

    public void builderCourseName(String courseName) {
        course.setCourseName(courseName);
    }

    public void builderCoursePPT(String coursePPT) {
        course.setCoursePPT(coursePPT);
    }

    public void builderCourseVideo(String courseVideo) {
        course.setCourseVideo(courseVideo);
    }

    public void builderCourseArticle(String courseArticle) {
        course.setCourseArticle(courseArticle);
    }

    public void builderCourseQA(String courseQA) {
        course.setCourseQA(courseQA);
    }

    public Course makeCourse() {
        return course;
    }
}

Coach类,是一个指挥者类,应用层可以通过指挥者类进行产品实例的创建,而不是直接调用建造者类的相关方法。

package com.kaven.design.pattern.creational.builder;

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.builderCourseName(courseName);
        this.courseBuilder.builderCoursePPT(coursePPT);
        this.courseBuilder.builderCourseVideo(courseVideo);
        this.courseBuilder.builderCourseArticle(courseArticle);
        this.courseBuilder.builderCourseQA(courseQA);
        return this.courseBuilder.makeCourse();

    }
}

应用层代码:

package com.kaven.design.pattern.creational.builder;

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

结果:

Course{courseName='Java设计模式', coursePPT='Java设计模式PPT', courseVideo='Java设计模式视频', courseArticle='Java设计模式手记', courseQA='Java设计模式问答'}

这便是一个建造者模式的例子,不过看起来还是挺复杂的。

改进
使用静态内部类可以改进建造者模式。

Course类(课程类),与上面的Course类一样,是一个产品类。
但在Course类中定义了一个静态内部类CourseBuilder,并且这个静态内部类CourseBuilder就是课程实例的实际建造者,可以好好体会下面的代码。

package com.kaven.design.pattern.creational.builder.v2;

public class Course {

    private String courseName;
    private String coursePPT;
    private String courseVideo;
    private String courseArticle;

    //question and answer
    private String courseQA;

    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;

        //question and answer
        private String courseQA;

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

应用层代码:

由于上面的改进,创建课程实例的建造者模式更加简洁,并且在应用层创建课程实例时更加友好(通过链式调用对课程实例属性进行初始化,关键在于静态内部类CourseBuilder中的buildxxx()方法都是返回this)。
根据静态内部类CourseBuilder中的代码可以看出,每次调用buildxxx()方法其实都是初始化静态内部类CourseBuilder实例的xxx属性,最后通过调用build()方法,将this传给Course类的构造方法创建课程实例(此时this的属性都已经有值了,再通过this的这些属性值来初始化课程实例的属性)。

package com.kaven.design.pattern.creational.builder.v2;

public class Test {
    public static void main(String[] args) {
        Course course = new Course.CourseBuilder().buildCourseName("Java设计模式")
                .buildCoursePPT("Java设计模式PPT").buildCourseVideo("Java设计模式视频")
                .buildCourseArticle("Java设计模式手记").buildCourseQA("Java设计模式问答").build();
        System.out.println(course );
    }
}

与未改进的版本相比,通过链式调用对课程实例属性进行初始化更加友好,还不容易出错,像下面创建课程实例的代码,属性值很容易写错位置,改进版本的建造者模式在很多中间件以及框架中有使用。

Course course = coach.makeCourse("Java设计模式","Java设计模式PPT",
                "Java设计模式视频","Java设计模式手记","Java设计模式问答");

结果是一样的。

Course{courseName='Java设计模式', coursePPT='Java设计模式PPT', courseVideo='Java设计模式视频', courseArticle='Java设计模式手记', courseQA='Java设计模式问答'}

如果有说错的地方,请大家不吝赐教(记得留言哦~~~~)。

发布了258 篇原创文章 · 获赞 161 · 访问量 32万+

猜你喜欢

转载自blog.csdn.net/qq_37960603/article/details/104029347