设计模式-建造者模式(Builder Pattern)
原创
©著作权归作者所有:来自51CTO博客作者ITKaven的原创作品,请联系作者获取转载授权,否则将追究法律责任
推荐:Java设计模式汇总
建造者模式
定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
创建者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象。
类型
创建型。
例子
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设计模式问答'}
适用场景
- 需要生成的产品对象有复杂的内部结构,这些产品对象具备共性。
- 隔离复杂对象的创建和使用,并使得相同的构建过程可以创建不同的产品。
建造者模式与抽象工厂模式的比较
- 与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
- 在抽象工厂模式中,应用层实例化工厂类,然后调用工厂方法获取所需产品对象,
而在建造者模式中,应用层可以不直接调用建造者类的相关方法,而是通过指挥者类来指导如何生成对象
,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象。 - 如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车
设计模式-抽象工厂模式(Abstract Factory Pattern)
优点
- 使用建造者模式可以使应用层不必知道产品内部组成的细节。
- 具体的建造者类之间是相互独立的,这有利于系统的扩展。
- 具体的建造者相互独立,因此可以对建造的过程逐步细化,而不会对其他模块产生任何影响。
缺点
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
如果有说错的地方,请大家不吝赐教(记得留言哦~~~~)。