建造者模式
建造者模式是一种创建型设计模式,它允许逐步构建复杂对象,并且能够使构建过程和表示分离。这样做的好处是可以在不改变最终产品结构的情况下,提供不同的构造选项,只需要通过选择不同的建造者模式就能得到不同的对象,具体构建的过程和细节就不需要知道。
标准建造者模式:
核心:
- Product(产品角色):需要被构建的复杂对象。
- Builder(抽象建造者):定义了构建 Product 对象各个部分的接口或抽象类。
- ConcreteBuilder(具体建造者):实现了 Builder 接口,提供构建 Product 对象的具体实现。
- Director(指挥者):使用 ConcreteBuilder 来构建复杂的对象。负责控制产品的生成过程,但并不知道具体的构建细节。
使用场景
说明与示例 | |
---|---|
对象创建参数过多 | 当构造一个对象需要大量参数,尤其是很多是可选参数时,避免“构造函数爆炸”。 例如: Person(name, age, address, phone, email...) 。 |
构建过程复杂或步骤多 | 构建对象需要多个步骤、顺序明确,每个步骤可能独立变化。 例如:构建一个 Computer 需要安装 CPU、内存、硬盘等。 |
构建不同表现形式的对象 | 同样的构建流程,生成不同的产品实例。 例如:制作不同类型的汉堡套餐(儿童套餐、家庭套餐)。 |
希望解耦构建逻辑和表示细节 | 客户端不需要知道对象如何一步步构建,只需要指定类型即可。 例如:游戏中的角色构建器(战士/法师/弓箭手)。 |
支持链式调用(Fluent Interface) | 提供更优雅、易读的 API 调用方式。 例如: User user = new UserBuilder().setName("Tom").setAge(25).build(); |
避免使用 JavaBean 方式设置属性带来的不一致性风险 | 在构建过程中保证对象的状态一致性,而不是逐步赋值导致中间状态错误。 例如:某些字段必须在构建时就完成初始化。 |
用于不可变对象(Immutable Object)的构建 | 如果对象是不可变的(final 字段),不能通过 setter 设置,建造者模式非常适合。 例如:Java 中的 BigDecimal 或自定义的不可变类。 |
示例:
java
@Slf4j
@Data
public class Product {
private String name;
private String packing ;
private BigDecimal price;
private String desc;
public void show(){
log.info("产品名称: {}, 包装方式: {}, 价格: {}, 描述: {}", name, packing, price, desc);
}
}
java
public abstract class ProductBuilder {
protected Product product;
public abstract void setPacking();
public abstract void setName();
public abstract void setPrice();
public abstract void setDesc();
public Product getProduct() {
return product;
}
}
java
public class KrustyKrabProductBuilder extends ProductBuilder {
public KrustyKrabProductBuilder() {
this.product = new Product();
}
@Override
public void setPacking() {
product.setPacking("纸盒装");
}
@Override
public void setName() {
product.setName("蟹黄堡");
}
@Override
public void setPrice() {
product.setPrice(new BigDecimal("5.00"));
}
@Override
public void setDesc() {
product.setDesc("蟹黄堡desc");
}
}
java
public class ProductDirector {
private ProductBuilder builder;
public ProductDirector(ProductBuilder builder) {
this.builder = builder;
}
public Product createProduct() {
builder.setPacking();
builder.setName();
builder.setPrice();
builder.setDesc();
return builder.getProduct();
}
}
内部类建造者
核心:
在需要建造者的类中创建一个内部的建造者,建造者中的方法中返回建造者本身,通过内部的建造者链式调用的方式进行属性赋值,最后通过 build 方法创建对象。
示例:
java
public class Product {
private String name;
private String packing ;
private BigDecimal price;
private String desc;
private Product(Builder builder) {
this.name = builder.name;
this.packing = builder.packing;
this.price = builder.price;
this.desc = builder.desc;
}
public static class Builder{
private String name;
private String packing ;
private BigDecimal price;
private String desc;
public Builder name(String name) {
this.name = name;
return this;
}
public Builder packing(String packing) {
this.packing = packing;
return this;
}
public Builder price(BigDecimal price) {
this.price = price;
return this;
}
public Builder desc(String desc) {
this.desc = desc;
return this;
}
public Product build() {
return new Product(this);
}
}
}
java
public class Main {
public static void main(String[] args) {
Product build = new Product.Builder()
.name("可乐")
.packing("瓶装")
.price(new BigDecimal("3.00"))
.desc("可乐desc")
.build();
}
}