1. 程式人生 > >java設計模式——建造者模式

java設計模式——建造者模式

一. 定義與型別

定義:將一個複雜物件的構建與它的表示分離,使用同樣的構建過程可以建立不同的表示

使用者只需制定需要建造的型別就可以得到它們,建造過程以及細節不需要知道

型別:建立型

建造者模式與工廠模式比較相近,它們的區別在於,

建造者模式注重方法的呼叫順序,工廠模式注重建立產品

它們的建立力度不同,建造者模式可以建立較為複雜產品,有各種複雜的部件,而工廠模式創建出來的產品都是一個樣子

工廠模式關注的只要把這個產品創建出來就行了,建造者模式不僅要把產品創建出來,還要知道這個產品有哪些部件組成

二. 適用場景

如果一個物件有非常複雜的內部結構(很多熟悉),想把複雜物件的建立和使用分離

三. 優缺點

優點:

封裝性好,建立和使用分離

擴充套件性好,建造類之間獨立,一定程度上解耦

缺點:

產生多餘的Builder物件

產品內部發生變化,建造者都要修改,成本較大

四. Coding

建立一個抽象的課程建造類:

/**
 * @program: designModel
 * @description:
 * @author: YuKai Fan
 * @create: 2018-12-03 16:48
 **/
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(); }

建立一個實際的建造類:

/**
 * @program: designModel
 * @description:
 * @author: YuKai Fan
 * @create: 2018-12-03 16:50
 **/
public class CourseActualBuilder extends CourseBuilder{
    private Course course = new Course();

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

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

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

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

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

    public Course makeCourse() {
        return course;
    }
}

建立建造者實體類:

/**
 * @program: designModel
 * @description:
 * @author: YuKai Fan
 * @create: 2018-12-03 16:52
 **/
public class Coach {
    private CourseBuilder courseBuilder;

    //通過set注入,傳入的課程建造的值
    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.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 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);
    }
}

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 class Course {
    private String courseName;
    private String coursePPT;
    private String courseVideo;
    private String courseArticle;

    //question & 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;
    }

    //內部類
    public static class CourseBuilder{
        private String courseName;
        private String coursePPT;
        private String courseVideo;
        private String courseArticle;

        //question & 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);
        }
    }

    @Override
    public String 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 class Test {
    public static void main(String[] args) {
        Course course= new Course.CourseBuilder().buildCourseName("Java設計模式").buildCoursePPT("Java設計模式PPT").buildCourseVideo("Java設計模式視訊").buildCourseQA("Java設計模式問答").build();
        System.out.println(course);
    }
}

UML類圖:

這種方式,在實際應用當中用的比較多,以後的維護都會比較方便

五. 原始碼分析

使用最多最常用的StringBuilder,StringBuffer它們的append方法。就是使用了建造者模式,也是使用的鏈式呼叫.

CacheBuilder方法,也是典型的建造者模式

Spring中的BeanDefinitionBuilder,Mybatis中的SqlSessionFactoryBuilder