在软件系统的设计中,建造者模式是一种常用的设计模式,也称为Builder模式,属于创造型模式。建造者模式实现起来非常简单,但是如果我们需要灵活的使用一种模式,我们必须清楚的知道这种模式产生的原因以及他能解决的是什么样的问题?
在JAVA程序中,对于一个类的创建,直接用关键字new即可,这种情况一般属于对象结构比较简单,没有复杂依赖的场景,当我们需要对一个类进行比较复杂的构造的时候,比如拥有很多的属性,我们常见的处理方式是有两种
一、依托于构造器,在构造器中声明多个属性。
二、生成set方法,在set方法中对属性进行赋值操作。
这两场方式存在一定的弊端,
如果依托于构造器,当我们的属性都需要进行注入的时候,构造器会变得异常庞大,如果新增了属性,那我们需要对原构造器,进行新增字段或者生成新的构造器,这样不符合设计原则中的对修改关闭,对扩展开放,又使的构造器在代码的可读性和易用性上变的非常的差,而且在进行赋值的过程中,如果有些属性,并不需要使用,依然需要为这个属性设置默认值。
如果使用生成set方法的方式去构建,虽然可以解决构造器沉重,难以维护的情况,但是如果我们在设计的时候,各个属性之前拥有强烈依赖关系,比如Person类的构建,需要拥有ear,eye,mouth等属性,当我们使用set的方式的时候去设置,又会导致Person类的不完整性,例如只赋值了head, 因此我们发现使用set方法的方式不能解决代码的完整性校验。
为了解决这些问题,软件大师设计出了Builder模式,我们先看代码实现。
package com.zyc.to.common;
/**
* @Description:
* @Modify By:
*/
public class Person {
//隐藏构造器
private Person() {
}
private Person(Builder builder) {
this.ears = builder.ears;
this.mouths = builder.mouths;
this.eyes = builder.eyes;
}
private int eyes;
private int mouths;
private int ears;
public int getEars() {
return ears;
}
public int getMouths() {
return mouths;
}
public int getEyes() {
return eyes;
}
static class Builder {
private int eyes;
private int mouths;
private int ears;
public Builder eyes(int eyes) {
this.eyes = eyes;
return this;
}
public Builder mouths(int mouths) {
this.mouths = mouths;
return this;
}
public Builder ears(int ears) {
this.ears = ears;
return this;
}
public Person build() {
if(this.ears == 2 && this.eyes == 2 && this.mouths == 1) {
return new Person(this);
}else
throw new IllegalArgumentException("参数错误");
}
}
public static void main(String[] args) {
Person person = new Person.Builder().ears(2).eyes(1).mouths(1).build();
}
}
这种实现方式,将校验逻辑封装在build方法中,保证了类的完整性,又能灵活调配属性,对于复杂的构建也可以进行很好的扩展。我们总结一下构建者模式的使用场景,避免过度使用。
如果类的构建需要很多属性的赋值操作,严重影响代码的可读性和复用性;
如果类的构建过程非常复杂,需要对使用者透明,增加类的易用性,或者类一旦生成不可再变;
如果类在构建的时候属性之间拥有多重依赖关系,需要保证类的完整性。
除了我们自己生成构建者模式还有一种直接使用Lombok的方式自动生成,比较简单,直接贴上代码
package com.zyc.cn;
import lombok.Builder;
import lombok.Data;
/**
* @Description:
* @Date:Created in 2020/3/13- 21:19
* @Modify By:
*/
@Builder
@Data
public class Person {
private int eyes;
private int mouths;
private int ears;
public static void main(String[] args) {
Person person = Person.builder().eyes(2).mouths(1).ears(2).build()
}
}
反编译后生成的代码:
package com.zyc.co;
public class Person {
private int eyes;
private int mouths;
private int ears;
public static void main(String[] args) {
Person person = builder().eyes(2).mouths(1).ears(2).build();
}
Person(int eyes, int mouths, int ears) {
this.eyes = eyes;
this.mouths = mouths;
this.ears = ears;
}
public static PersonBuilder builder() {
return new PersonBuilder();
}
public int getEyes() {
return this.eyes;
}
public int getMouths() {
return this.mouths;
}
public int getEars() {
return this.ears;
}
public void setEyes(int eyes) {
this.eyes = eyes;
}
public void setMouths(int mouths) {
this.mouths = mouths;
}
public void setEars(int ears) {
this.ears = ears;
}
public static class PersonBuilder {
private int eyes;
private int mouths;
private int ears;
public PersonBuilder eyes(int eyes) {
this.eyes = eyes;
return this;
}
public PersonBuilder mouths(int mouths) {
this.mouths = mouths;
return this;
}
public PersonBuilder ears(int ears) {
this.ears = ears;
return this;
}
public Person build() {
return new Person(this.eyes, this.mouths, this.ears);
}
public String toString() {
return "Person.PersonBuilder(eyes=" + this.eyes + ", mouths=" + this.mouths + ", ears=" + this.ears + ")";
}
}
}