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类图:
这种方式,在实际应用当中用的比较多,以后的维护都会比较方便。
无论那种方式,建造者模式,将产品的构造,组件都分离开。从上面的例子可以看出,course的创建(具体过程),启动course的创建(coach来创建),创建哪种course(test应用层)都分的清清楚楚,即模块化,达到了模块分离的效果。这样维护和扩展都很方便
五. 源码分析
使用最多最常用的StringBuilder,StringBuffer它们的append方法。就是使用了建造者模式,也是使用的链式调用.
CacheBuilder方法,也是典型的建造者模式
Spring中的BeanDefinitionBuilder,Mybatis中的SqlSessionFactoryBuilder