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