Java创建型设计模式,建造者模式(Builder Pattern)是23种设计模式当中创建型最后一个了,之前小编讲了单例、原型、工厂方法,抽象工厂,对小编学习的一个记录。
当然设计模式这种概念性的玩意,也不是说花上一段时间来学习就能熟练掌握的,不仅仅要对每一种设计模式有所了解,并且能够合理的使用到系统当中,这需要一个长期的巩固学习以及实际操作才能慢慢成熟。
设计模式小编从前几个月就开始慢慢的在学习,在学校老师只讲了常用的单例、代理,工厂等常见的设计模式,没有很系统的学习,在工作当中随着需求的变更,改造的地方很多,功能在当初开发设计的时候就很不合理。
还能怎么办,只能针对自己弱项好好学习了,能够发现自己的不足,就是好的表现嘛哈哈哈哈哈哈。
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的的表示。用户只需要指定需要建造的类型,建造者负责按顺序创建复杂对象,建造的过程以及细节不需要知道。
这个建造者模式和工厂模式有异曲同工之妙,都是对外隐藏创建细节,当创建一个复杂对象需要很多步骤时,合适使用建造者模式,而当只需要一个简单的方法创建整个对象时,使用工厂模式。
优缺点:方便用户创建复杂的对象,其次就是代码的复用性和封装性,创建和使用分离开来,建造类之间的独立,扩展性较好。但优点虽好,随之而来的缺点也就显而易见了,建造类之间独立会增加类的个数,如果产品内部发生了变化,建造者修改的成本相对较大。
标准型建造者模式有这么几个角色:
1、产品 Product (即对象):一个具体的产品对象
2、抽象建造者 Builder:定义一个产品对象的各个部件指定的接口或者抽象类。
3、具体建造者 ConcreteBuilder:实现抽象建造者接口,构建和装配各个部件。
4、指挥者 Director:主要是用于创建一个复杂的对象。主要作用有两个,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。
案例分析:
现在某网站需要实现一个课程的功能,这里课程就是我们的产品。
网站的负责人定义了课程必须包括课程名字、课程教学视频、课程手记三个部分,这三个部分就是抽象的建造者。
现在有一位教学Java的老师,由他负责提供课程名字、录制教学视频、记录笔记,这位老师就是具体的建造者。
老师把课程名字、视频、手记都弄好了,现在他要将这些文件给网站的后台的管理人员,由管理人员进行控制对外发布课程这个产品,这个管理人员就是指挥者。
代码实现:
产品对象:Java教学课程,课程包括课程名字、课程视频、课程手记,三个部分组
/**
* @Auther: IT贱男
* @Date: 2019/8/11 10:41
* @Description: 产品对象
*/
@Data
public class Course {
/**
* 课程名字
*/
private String courseName;
/**
* 课程视频
*/
private String courseVideo;
/**
* 课程手记
*/
private String courseNote;
@Override
public String toString() {
return "Course{" +
"courseName='" + courseName + '\'' +
", courseVideo='" + courseVideo + '\'' +
", courseNote='" + courseNote + '\'' +
'}';
}
}
抽象建造者:定义构建课程产品的三个步骤,并且需要获取产品的方法
/**
* @Auther: IT贱男
* @Date: 2019/8/11 10:44
* @Description: 抽象建造者
*/
public abstract class CourseBuilder {
/**
* 课程名字实现方法
*/
abstract void builderCourseName();
/**
* 教学视频实现方法
*/
abstract void builderCourseVideo();
/**
* 课程手记实现方法
*/
abstract void builderCourseNote();
/**
* 制造课程
*
* @return
*/
abstract Course makeCourse();
}
具体建造者:创建一个Java具体建造者,并实现抽象建造者方法
/**
* @Auther: IT贱男
* @Date: 2019/8/11 10:46
* @Description: Java课程具体建造者
*/
public class JavaCourseBuilder extends CourseBuilder {
private Course course = new Course();
@Override
public void builderCourseName() { course.setCourseName("Java课程"); }
@Override
public void builderCourseVideo() { course.setCourseVideo("java视频");}
@Override
public void builderCourseNote() { course.setCourseNote("java笔记"); }
@Override
public Course makeCourse() { return course; }
}
指挥者 Director:主要是用于创建一个复杂的对象。主要作用有两个,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。
/**
* @Auther: IT贱男
* @Date: 2019/8/11 10:48
* @Description: 指挥者
*/
public class Coach {
private CourseBuilder courseBuilder;
public void setCourseBuilder(CourseBuilder courseBuilder) {
this.courseBuilder = courseBuilder;
}
public Course makeCourse() {
courseBuilder.builderCourseName();
courseBuilder.builderCourseVideo();
courseBuilder.builderCourseNote();
return courseBuilder.makeCourse();
}
}
客户端调用
public static void main(String[] args) {
// 创建一个指挥者
Coach coach = new Coach();
coach.setCourseBuilder(new JavaCourseBuilder());
// 建造课程
Course course = coach.makeCourse();
System.out.println(course);
}
还有一种实现方式就是通过内部类来实现,这种方式比较常用, 比较灵活。
为什么说灵活呢? 使用内部类缺少了指挥者,由用户来充当指挥者的角色,使产品更加灵活。
内部类建造者还有一种使用场景,就是当我们构造器有很多参数参数的时候,如果都全部写在构造器里面可读性很差,而且也会出现传错都情况,这个时候我们就可以采用build模式来实现。
/**
* @Auther: IT贱男
* @Date: 2019/8/11 10:41
* @Description: 定义一个产品类
*/
public class Course {
private String courseName;
private String courseVideo;
private String courseNote;
public Course(CourseBuilder builder) {
this.courseName = builder.courseName;
this.courseVideo = builder.courseVideo;
this.courseNote = builder.courseNote;
}
@Override
public String toString() {
return "Course{" +
"courseName='" + courseName + '\'' +
", courseVideo='" + courseVideo + '\'' +
", courseNote='" + courseNote + '\'' +
'}';
}
/**
* 产品的建造者
*/
static class CourseBuilder {
private String courseName;
private String courseVideo;
private String courseNote;
public CourseBuilder builderCourseName(String courseName) {
this.courseName = courseName;
return this;
}
public CourseBuilder builderCourseVideo(String courseVideo) {
this.courseVideo = courseVideo;
return this;
}
public CourseBuilder builderCourseNote(String courseNote) {
this.courseNote = courseNote;
return this;
}
public Course build() {
return new Course(this);
}
}
}
public static void main(String[] args) {
Course course = new Course.CourseBuilder().builderCourseName("Java课程").build();
System.out.println(course);
}
小编来解释一下这段代码。
Course:这个是一个课程产品类,里面包含了课程需要的三个部分。
Course中有一个内部类叫CourseBuilder类,它负责提供对外建造的方法,最后调用build方法完成对象的建造。
在这里用户可根据CourseBuilder所提供的方法,灵活使用。
1、客户端(使用程序)不必知道产品内部组成的细节,将产品本身与产品的创建过程结耦,使的相同的创建过程可以创建不同的产品对象。
2、每一个具体建造者相对独立,因此可以很方便替换具体建造者或者新增具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。
3、可以更加精细控制产品创建过程。将复杂产品的创建步骤分解在不同的方法中,是的创建过程更加清晰,也更方便使用程序控制创建产品对象。
4、增加新的具体建造者无需修改原有的代码,指挥者对面抽象建造者编程,系统扩展方便,符合开闭原则。