目录
前言
建造者模式适用于构建复杂对象,并将对象的构建过程和最终表示相互分离,使得同样的构建过程可以创建不同的表示。要构建的对象的成员变量需要有较好的稳定性,不会轻易增加或者删除,且一般都有默认值
理论上使用建造者模式时,需要创建的对象相对复杂,有多个组成部分且这些部分的构建顺序可能不同,也可能需要不同的构建过程。
实际上,即便是简单对象也能直接套用建造者模式,构造过程链式调用,代码可读性更好。
UML
plantuml
@startuml 'https://plantuml.com/class-diagram class Product { - partA : type - partB : type + Product(Builder) } class Builder { - partA : type - partB : type + {static} buildPartA() : this + {static} buildPartB() : this + {static} build() : Product } class Client { + {static} main(String[]) : void } Builder ..> Product Client ..> Builder Client ..> Product @enduml
类图
实战代码
JDK Calendar
JDK 的 Calendar 使用静态内部类实现 Builder,将构造过程分离出来。
public class BuilderTest {
public static void main(String[] args) {
//jdk Calendar 用了静态内部Build类
Calendar now = new Calendar.Builder()
.setLocale(Locale.getDefault())
.setTimeZone(TimeZone.getDefault())
.build();
System.out.println(now.get(Calendar.YEAR));
}
}
Lombok @Builder
基于 @Buider,用建造者模式链式调用建造方法创建简单对象实例,代码可读性更好。
public class BuilderTest {
public static void main(String[] args) {
SimpleClass simpleClass = SimpleClass.builder()
.id("1")
.name("abc")
.build();
}
@Builder
public class SimpleClass {
private String id;
private String name;
}
}
静态内部类实现建造者模式
实际业务开发中,可能会遇到相当繁杂的业务处理,代码行数特别多,这时就可以将业务代码用面向对象的方式来表示,构造一个业务对象专门来处理这个业务。而业务对象的创建就能够使用建造者模式。
借鉴 JDK Calendar 的写法,在业务对象中写一个静态内部类,实现建造者模式,最终创建复杂业务对象。
业务对象(简化)
public class BizEntity {
private final String type;
private final String size;
private BizEntity(Builder builder) {
this.type = builder.type;
this.size = builder.size;
}
public static class Builder {
private String type = "1";
private String size = "L";
public Builder(){}
public Builder type(String type) {
this.type = type;
return this;
}
public Builder size(String size) {
this.size = size;
return this;
}
public BizEntity build(){
return new BizEntity(this);
}
}
}
测试类
public class BuilderTest {
public static void main(String[] args) {
BizEntity bizEntity1 = new BizEntity.Builder().type("1").size("L").build();
BizEntity bizEntity2 = new BizEntity.Builder().type("2").size("M").build();
System.out.println(bizEntity1.toString());
System.out.println(bizEntity2.toString());
}
}