在工作中我们经常遇到参数比较多的构造函数,构造函数的参数可能很快就会失控,而且可能很难理解每个参数。如果将来你想添加参数,或者改变参数,这个参数列表还可能更快增长,很容易出错。例如生成下面的“英雄”角色,选择职业、性别、头发颜色等,角色的生成就变成了一个一步一步的过程,当所有的选择都准备好了,这个过程就完成了。
public Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) {
}
我们可以利用java中的构造者设计模式进行重构,首先有我们想要的“英雄”。
public final class Hero {
private final Profession profession;
private final String name;
private final HairType hairType;
private final HairColor hairColor;
private final Armor armor;
private final Weapon weapon;
private Hero(Builder builder) {
this.profession = builder.profession;
this.name = builder.name;
this.hairColor = builder.hairColor;
this.hairType = builder.hairType;
this.weapon = builder.weapon;
this.armor = builder.armor;
}
}
然后是建造者:
public static class Builder {
private final Profession profession;
private final String name;
private HairType hairType;
private HairColor hairColor;
private Armor armor;
private Weapon weapon;
public Builder(Profession profession, String name) {
if (profession == null || name == null) {
throw new IllegalArgumentException("profession and name can not be null");
}
this.profession = profession;
this.name = name;
}
public Builder withHairType(HairType hairType) {
this.hairType = hairType;
return this;
}
public Builder withHairColor(HairColor hairColor) {
this.hairColor = hairColor;
return this;
}
public Builder withArmor(Armor armor) {
this.armor = armor;
return this;
}
public Builder withWeapon(Weapon weapon) {
this.weapon = weapon;
return this;
}
public Hero build() {
return new Hero(this);
}
}
然后调用方法:
var mage = new Hero.Builder(Profession.MAGE, "Riobard")
.withHairColor(HairColor.BLACK)
.withWeapon(Weapon.DAGGER).build();
类图:
builder.png
Real world examples
- java.lang.StringBuilder
- java.nio.ByteBuffer as well as similar buffers such as FloatBuffer, IntBuffer and so on.
- java.lang.StringBuffer
- All implementations of java.lang.Appendable
- Apache Camel builders
- Apache Commons Option.Builder