一、前言
《Effective Java》读书笔记系列
第二章 第1条:创建和销毁对象
第二章 第2条:遇到多个构造器参数时要考虑使用Builder
二、介绍
我们开发中偶尔会遇到一些需要设置10个或以上
大量参数的情况,通常情况有几种处理方式:多构造函数、setter
、Builder模式
。
- 1、多构造函数:这种方式虽然最方便,但也最繁琐,假设有一个方法需要设置
6
个int
型的参数,但多数情况下,这6
个中总有你不想传的参数,这时候就需要约定一个规则:例如传0
,但是传0
又会有一个问题就是传入顺序问题
,传入顺序不同并不会导致程序编译不通过
,却会导致程序运行结果不正确
。所以这并不是一种好方式 - 2、
setter
:
虽然它可以解决多构造带来的传入顺序问题,但是它还是略显繁琐了。所以我们通常只会在JavaBean
中使用setter
- 3、
Builder模式
: - 本文要介绍的一种方式,可以完美解决上述两种方式带来的弊端,让代码更加符合设计模式。参考
Glide
和Retrofit
的使用方式,它们都是通过链式调用
一个一个参数连接起来的
三、定义
Builder
的定义是:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
四、使用场景
主要强调两点:调用顺序
、多参数
- 1、相同的方法,不同的执行顺序,需要产生不同的事件结果时
- 2、多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同的时候
- 3、产品类非常复杂,或者产品类中的调用顺序不同产生了不同的作用时
- 4、当初始化一个对象特别复杂,如参数多,且很多参数都具有默认值时
四、UML图
背景:我要建造一个xsic
在这个背景下,Product
是xsic
的抽象,也就是人,ConcreteBuilder
是一个具体Builder
类,继承了抽象Builder
类Builder
,而Director
可以是一个高层客户端模块,也可以是一个为高层客户端模块提供构建功能的中间模块
四、举例
1、抽象产品类,在UML
中没有具体体现
public abstract class Person {
protected String mHead;
protected int mBody;
protected String mArm;
protected String mLeg;
protected String mHair;
public abstract void setHead(String head);
public abstract void setBody(int body);
public void setmArm(String mArm) {
this.mArm = mArm;
}
public void setmLeg(String mLeg) {
this.mLeg = mLeg;
}
public void setmHair(String mHair) {
this.mHair = mHair * mBody;
}
}
2、具体产品类,对应UML
中的Product
public class Xsic extends Person {
public Xsic() {
}
@Override
public void setHead(String head) {
mHead = "默认头";
}
@Override
public void setBody(int body) {
mBody = 1;
}
}
3、抽象Builder类,对应UML
中的Builder
public abstract class Builder {
public abstract Builder buildHead(String head);
public abstract Builder buildBody(int body);
public abstract Builder buildArm(String arm);
public abstract Builder buildLeg(String leg);
public abstract Builder buildHair(String hair);
public abstract Person build();
}
4、具体Builder类,对应UML
中的ConcreteBuilder
public class XsicBuilder extends Builder {
private Xsic xsic = new Xsic();
@Override
public Builder buildHead(String head) {
xsic.setHead(head);
return this;
}
@Override
public Builder buildBody(int body) {
xsic.setBody(body);
return this;
}
@Override
public Builder buildArm(String arm)