这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战
建造者模式
是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象。
优点
- 封装性好,构建和表示分离。
- 扩展性好,各个具体的建造者相互独立,有利于系统的解耦。
- 客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险。
缺点
- 产品的组成部分必须相同,这限制了其使用范围。
- 如果产品的内部变化复杂,如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大。
使用场景
当一个类的构造函数参数个数超过4个,而且这些参数有些是可选的参数,考虑使用构造者模式。
结构
- 产品角色(Product):最终生成的对象;它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。
- 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
- 具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
- 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
传统演示
1、产品类
public class Jacket {
private Integer sleeve;
private Integer buttons;
private Integer pocket;
}
2、Builder类
public abstract class Builder {
abstract void buildSleeve();
abstract void buildButtons();
abstract void buildPocket();
abstract Jacket createJacket();
}
3、Concrete Builder类
建造具体的产品, 指定具体产品各部件需要的值
public class LiningJacketBuilder extends Builder{
private Jacket jacket = new Jacket();
@Override
void buildSleeve(int sleeve) {
this.jacket.setSleeve(sleeve);
}
@Override
void buildButtons(int buttons) {
this.jacket.setButtons(buttons);
}
@Override
void buildPocket(int pocket) {
this.jacket.setPocket(pocket);
}
@Override
Jacket createJacket() {
return this.jacket;
}
}
4、Director
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public Jacket construct(int sleeve, int buttons, int pocket) {
this.builder.buildSleeve(sleeve);
this.builder.buildButtons(buttons);
this.builder.buildPocket(pocket);
return this.builder.createJacket();
}
}
5、客户端
public class Click {
public static void main(String[] args) {
Director director = new Director(new LiningJacketBuilder());
Jacket jacket = director.construct(2,5,1);
System.out.println(jacket.toString());
// Jacket [sleeve=2, buttons=5, pocket=1]
}
}
总结
传统的建造者模式跟工厂模式有些类型,都是返回一个具体产品。
- 区别1:Director类似将产品各个部件组装成一个产品,而工厂直接生产一个产品
- 区别2:工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象;而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象 。
- 区别3:工厂模式最终是构建一个对象,而建造者模式的目的是构建一个复杂不可变对象
简化演示
- 在Jacket 中创建一个静态内部类 Builder,然后将Computer 中的参数都复制到Builder类中。
- 在Jacket中创建一个private的构造函数,参数为Builder类型
- 在Builder中创建一个public构造函数
- 在Builder中创建设置函数,对Jacket中那些可选参数进行赋值,返回值为Builder类型的实例
- 在Builder中创建一个build()方法,在其中构建Jacket的实例并返回
public class Jacket {
private Integer sleeve;
private Integer buttons;
private Integer pocket;
private Jacket(Builder builder) {
this.sleeve = builder.sleeve;
this.buttons = builder.buttons;
this.pocket = builder.pocket;
}
public static class Builder{
private Integer sleeve;
private Integer buttons;
private Integer pocket;
public Builder() {}
public Builder setSleeve(int sleeve) {
this.sleeve = sleeve;
return this;
}
public Builder setButtons(int buttons) {
this.buttons = buttons;
return this;
}
public Builder setPocket(int pocket) {
this.pocket = pocket;
return this;
}
public Jacket build(){
return new Jacket(this);
}
}
@Override
public String toString() {
return "Jacket [sleeve=" + sleeve + ", buttons=" + buttons + ", pocket=" + pocket + "]";
}
}
在客户端使用链式调用,一步一步的把对象构建出来。
public class Click {
public static void main(String[] args) {
Jacket jacket = new Jacket.Builder().setButtons(5).setPocket(1).setSleeve(2).build();
System.out.println(jacket.toString());
// Jacket [sleeve=2, buttons=5, pocket=1]
}
}
总结
使用传统建造者模式,如果参数很多,代码可读性会非常差,而且容易引入错误。而重构简化后,上面的示例代码只是传入三个参数,如果参数是十几个甚至更多,builder 模式的优势将会更加明显,传递参数更加灵活,代码具有更高的可读性.
文章纯属个人见解,有不同见解可以在评论区一起讨论(*^▽^*)