这是创建型设计模式的最后一种模式,也是用来创建复杂的对象。
网上大多数例子,在讲解建造者模式时,都是用KFC套餐、做一道硬菜或者组装电脑等来举例,我们今天换一个例子,和我们程序员更贴近的例子。
俗话说:人在IT飘,哪能不通宵。
通宵多了之后,身体也感觉被渐渐掏空了,这个时候如果不注意保护身体,那么离ICU就不远了,我们程序员如何远离ICU呢?
1)磨练好技术,提升工作效率,减少加班。(安利一波:学技术哪家强,IT之美强中强,www.itzhimei.com)
2)定期体检了,用科学的检查提前预防疾病的发生。
今天的例子就以体检来演示。
体检我们都知道有很多项目,比如检查身高、体重、耳鼻喉、血压、心电图、菊花(gang men)等等十几项,有的体检甚至几十项,这些检查完成后,就是生成报告了。
我们用代码来对应报告,报告的bean定义为:
public class ExaminationReport {
private String name;
private String height;
private String weight;
private String heart;
private String ct;
private String eyes;
private String mouth;
//喉咙
private String throat;
//血压
private String bloodPressure;
//菊花--你懂得
private String juhua;
......这里略去十几项检查
}
我们要生成一个报告数据,要怎么生成呢?
一般的方式是不是在这个报告里,给每个属性生成set方法,new 一个ExaminationReport对象,然后写一大堆setXXX来赋值。
用上面的方法,就面临一个最重要的问题,就是这个体检报告是每个人的隐私,报告一旦生成,不希望被别人篡改,bean中有set方法,就意味着可以随便修改报告结果。
有同学说,可以用构造器。是的可以,但是因为参数太多,构造器的参数也会非常多,用起来也非常麻烦,像这种:
public ExaminationReport(String name,String height,String weight,
String heart,String ct,String eyes,
String mouth,String throat...) {......}
而且,这种方法还有一个问题是有些参数是必须、有些是不是必须的,那要根据每种情况,写对应的构造器,依旧非常麻烦。
那么,建造者模式就登场了,建造者模式就是让复杂对象的创建更加方便简单。
主要代码都在报告Bean中
import org.apache.commons.lang.StringUtils;
/**
* 体检报告Bean
*/
public class ExaminationReport {
private String name;
private String height;
private String weight;
private String heart;
private String ct;
private String eyes;
private String mouth;
//喉咙
private String throat;
//血压
private String bloodPressure;
//菊花--你懂得
private String juhua;
//public ExaminationReport(String name,String height,String weight,String heart,String ct,String eyes,String mouth,String throat...)
private ExaminationReport(ExaminationReportBuilder builder) {
this.name = builder.name;
this.height = builder.height;
this.weight = builder.weight;
this.heart = builder.heart;
this.ct = builder.ct;
this.eyes = builder.eyes;
this.mouth = builder.mouth;
this.throat = builder.throat;
this.bloodPressure = builder.bloodPressure;
this.juhua = builder.juhua;
}
public void printReport() {
System.out.println("***************体检报告***************");
System.out.println(this.name + "体检报告:");
System.out.println("身高:" + (StringUtils.isEmpty(this.height)?"---":this.height));
System.out.println("体重:"+ (StringUtils.isEmpty(this.weight)?"---":this.weight));
System.out.println("心率:"+ (StringUtils.isEmpty(this.heart)?"---":this.heart));
System.out.println("CT:"+ (StringUtils.isEmpty(this.ct)?"---":this.ct));
System.out.println("视力:"+ (StringUtils.isEmpty(this.eyes)?"---":this.eyes));
System.out.println("口腔:"+ (StringUtils.isEmpty(this.mouth)?"---":this.mouth));
System.out.println("喉咙:"+ (StringUtils.isEmpty(this.throat)?"---":this.throat));
System.out.println("血压:"+ (StringUtils.isEmpty(this.bloodPressure)?"---":this.bloodPressure));
System.out.println("菊花:"+ (StringUtils.isEmpty(this.juhua)?"---":this.juhua));
System.out.println("**************************************");
}
public static class ExaminationReportBuilder {
private String name;
private String height;
private String weight;
private String heart;
private String ct;
private String eyes;
private String mouth;
private String throat;
private String bloodPressure;
private String juhua;
public ExaminationReportBuilder(String name) {
this.name = name;
}
public ExaminationReportBuilder setHeight(String height) {
this.height = height;
return this;
}
public ExaminationReportBuilder setWeight(String weight) {
this.weight = weight;
return this;
}
public ExaminationReportBuilder setHeart(String heart) {
this.heart = heart;
return this;
}
public ExaminationReportBuilder setCt(String ct) {
this.ct = ct;
return this;
}
public ExaminationReportBuilder setEyes(String eyes) {
this.eyes = eyes;
return this;
}
public ExaminationReportBuilder setMouth(String mouth) {
this.mouth = mouth;
return this;
}
public ExaminationReportBuilder setThroat(String throat) {
this.throat = throat;
return this;
}
public ExaminationReportBuilder setBloodPressure(String bloodPressure) {
this.bloodPressure = bloodPressure;
return this;
}
public ExaminationReportBuilder setJuhua(String juhua) {
this.juhua = juhua;
return this;
}
public ExaminationReport build() {
return new ExaminationReport(this);
}
}
}
我们来具体看一下代码:
1、ExaminationReport就是报告bean,有各种检查结果属性,有打印报告的方法。
2、ExaminationReport有一个静态内部类:ExaminationReportBuilder
这个内部类作用就是ExaminationReport对象构建的实际建造者,在ExaminationReportBuilder中,每个成员方法都构建一个ExaminationReport的报告属性,并且这每个方法都返回ExaminationReportBuilder对象,为的是能够使用类似Lambda的语法,一直点出来各种属性去连续设置属性,效果如下:
ExaminationReport zhangsan = new ExaminationReport.ExaminationReportBuilder("张三")
.setHeight("170")
.setWeight("150")
.setHeart("70")
.setEyes("5.0")
.setMouth("正常")
.setBloodPressure("120-90")
.build();
3、ExaminationReportBuilder最后的build方法
public ExaminationReport build() {
return new ExaminationReport(this);
}
new出ExaminationReport,并将自己作为参数传入ExaminationReport构造器,也就是将set的各种值,传入到了ExaminationReport的构造器中进行构造,ExaminationReport的构造器中是这样用ExaminationReportBuilder的值的:
private ExaminationReport(ExaminationReportBuilder builder) {
this.name = builder.name;
this.height = builder.height;
this.weight = builder.weight;
this.heart = builder.heart;
this.ct = builder.ct;
this.eyes = builder.eyes;
this.mouth = builder.mouth;
this.throat = builder.throat;
this.bloodPressure = builder.bloodPressure;
this.juhua = builder.juhua;
}
这就实现了优雅的建造复杂对象的效果。
测试代码:
/**
* www.itzhimei.com
*/
public class Client {
public static void main(String[] args) {
ExaminationReport zhangsan = new ExaminationReport.ExaminationReportBuilder("张三")
.setHeight("170")
.setWeight("150")
.setHeart("70")
.setEyes("5.0")
.setMouth("正常")
.setBloodPressure("120-90")
.build();
zhangsan.printReport();
ExaminationReport xiaoming = new ExaminationReport.ExaminationReportBuilder("小明")
.setHeight("175")
.setWeight("165")
.setHeight("80")
.setEyes("4.5")
.setMouth("正常")
.setThroat("正常")
.setBloodPressure("120-90")
.setJuhua("痔疮")
.build();
zhangsan.printReport();
}
}
输出结果:
***************体检报告***************
张三体检报告:
身高:170
体重:150
心率:70
CT:---
视力:5.0
口腔:正常
喉咙:---
血压:120-90
菊花:---
**************************************
***************体检报告***************
张三体检报告:
身高:170
体重:150
心率:70
CT:---
视力:5.0
口腔:正常
喉咙:---
血压:120-90
菊花:---
**************************************
总结:
建造者模式就是让复杂对象的创建更加方便简单,将原本直接去new的对象,然后不停setXXX,修改为将这些工作交给一个职责类来处理,这是建造者的本质。