定义
将一个复杂对象的构建与表示分离,同样的构建过程创建不同的表示
- 构建:有些情况,一个对象的性质必须依赖于某个顺序赋值才有意义,这使得构建对象具有复杂的逻辑,因此,这个构建过程可以被外部化到一个叫建造者的对象里,建造者将构建好的产品返回给客户端
- 表示:一个产品有不同的组成部分,不同的产品有不同的组成部分,建造者模式使得客户端不用知道所生产的产品有哪些部分,有什么差异,是怎么构建出来的。就像房子,买房者得到的是修建好的房子,而不用关心房子是怎么建造好的
应用场景
- 产品较复杂,需要赋值的属性不一时
- 多个部件或零件都可以装配到一个对象上,但产生的结果不同
- 产品类中的调用顺序不同产生不同的结果
常用写法
标准写法
- 产品
/**
* 产品
*/
@Data
public class Product {
/**
* 需要建造的A部分
*/
private String partA;
/**
* 需要建造的B部分
*/
private String partB;
}
- 建造者接口
/**
* 建造者接口,定义行为
*/
public interface IBuilder {
/**
* 建造A部分
*/
void buildPartA();
/**
* 建造B部分
*/
void buildPartB();
/**
* 给出建造好的产品
*/
Product build();
}
- 实际的建造者
/**
* 实际的建造者,当只有一个建造者的时候,通常会省去IBuilder的定义
*/
public class ConcreteBuilder implements IBuilder {
private Product product = new Product();
@Override
public void buildPartA() {
product.setPartA("A");
}
@Override
public void buildPartB() {
product.setPartB("B");
}
@Override
public Product build() {
return product;
}
}
- 指挥者、调用者
/**
* 指挥者,负责产品部分完整建造或按顺序创建,就像建造房子时,施工队不和客户交流,而是有个管理者
* 指挥先建地基,后建房子,然后装修,最后交出建造好的房子给客户一样
*/
public class Director {
public static void main(String[] args) {
IBuilder builder = new ConcreteBuilder();
builder.buildPartA();
builder.buildPartB();
Product product = builder.build();
}
}
-
类图
建造者模式标准写法.png
lombock builder
- 原始代码
import lombok.Builder;
import lombok.Data;
/**
* 产品
*/
@Builder
@Data
public class Product {
/**
* 需要建造的A部分
*/
private String partA;
/**
* 需要建造的B部分
*/
private String partB;
}
- lombock 实际构建的builder
public class Product {
private String partA;
private String partB;
Product(final String partA, final String partB) {
this.partA = partA;
this.partB = partB;
}
public static Product.ProductBuilder builder() {
return new Product.ProductBuilder();
}
public String getPartA() {
return this.partA;
}
public String getPartB() {
return this.partB;
}
public void setPartA(final String partA) {
this.partA = partA;
}
public void setPartB(final String partB) {
this.partB = partB;
}
public boolean equals(final Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Product)) {
return false;
} else {
Product other = (Product)o;
if (!other.canEqual(this)) {
return false;
} else {
Object this$partA = this.getPartA();
Object other$partA = other.getPartA();
if (this$partA == null) {
if (other$partA != null) {
return false;
}
} else if (!this$partA.equals(other$partA)) {
return false;
}
Object this$partB = this.getPartB();
Object other$partB = other.getPartB();
if (this$partB == null) {
if (other$partB != null) {
return false;
}
} else if (!this$partB.equals(other$partB)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(final Object other) {
return other instanceof Product;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $partA = this.getPartA();
int result = result * 59 + ($partA == null ? 43 : $partA.hashCode());
Object $partB = this.getPartB();
result = result * 59 + ($partB == null ? 43 : $partB.hashCode());
return result;
}
public String toString() {
return "Product(partA=" + this.getPartA() + ", partB=" + this.getPartB() + ")";
}
public static class ProductBuilder {
private String partA;
private String partB;
ProductBuilder() {
}
public Product.ProductBuilder partA(final String partA) {
this.partA = partA;
return this;
}
public Product.ProductBuilder partB(final String partB) {
this.partB = partB;
return this;
}
public Product build() {
return new Product(this.partA, this.partB);
}
public String toString() {
return "Product.ProductBuilder(partA=" + this.partA + ", partB=" + this.partB + ")";
}
}
}
- 使用lombok的builder的好处
- 方便:只需要加一个@Builder,隐去了director和Ibuilder,帮助创建实际的建造者ProductBuilder,而不需要自己写
- 链式构建对象,不用一个一个去set
优缺点
优点
- 封装性好,创建和使用分离
- 扩展性好,建造类之间独立
缺点
- 产生多余的对象
- 产品改变时,建造者也需要一起跟着变
网友评论