建造者模式是一个比较抽象的设计模式,下面笔者忠于《设计模式:可复用面向对象软件的基础》书中的解释完成本文。
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象。
用户只需要给出指定复杂对象的类型和内容;建造者模式负责按既定规则创建复杂对象(把内部的建造过程和细节隐藏起来)
建造者模式通常包括下几个角色:
为了容易理解,这次设计一个场景——建设住宅建筑,Builder 为建筑工人抽象,Building 为住宅建筑抽象,Designer 为设计师。
下面的代码为设计师通过建筑工人建设普通住宅建筑和高层住宅建筑的代码:
// 住宅建筑抽象
public interface Building {
void addRooms(String room);
void addFloors(String floor);
List<String> getRooms();
List<String> getFloors();
void show();
}
// 具体住宅建筑
public class ResidenceBuilding implements Building {
List<String> rooms;
List<String> floors;
public ResidenceBuilding() {
this.rooms = new ArrayList<>();
this.floors = new ArrayList<>();
}
@Override
public void addRooms(String room) {
rooms.add(room);
}
@Override
public void addFloors(String floor) {
floors.add(floor);
}
@Override
public List<String> getRooms() {
return rooms;
}
@Override
public List<String> getFloors() {
return floors;
}
@Override
public void show() {
System.out.println("住宅房间:" + rooms.toString() + ";" +
"楼层:" + floors.toString() + "。");
}
}
// 建筑工人抽象
public interface Builder {
public void buildRoom(int n);
public void buildFloor(int m);
public Building getResult();
}
// 具体的住宅建筑工人
public class ResidenceBuilder implements Builder{
private Building building;
public ResidenceBuilder() {
this.building = new ResidenceBuilding();
}
@Override
public void buildRoom(int n) {
building.addRooms(n+"号房间");
}
@Override
public void buildFloor(int m) {
building.addFloors(m+"层");
}
@Override
public Building getResult() {
return building;
}
}
// 设计师
public class Designer {
private Builder builder;
public Designer(Builder builder) {
this.builder = builder;
}
public Building build() {
builder.buildRoom(1);
builder.buildRoom(2);
builder.buildRoom(3);
builder.buildRoom(4);
builder.buildFloor(1);
builder.buildFloor(2);
return builder.getResult();
}
public Building buildHigh() {
for (int i = 1; i <= 100; i++) {
builder.buildRoom(i);
if (i % 10 == 0) {
builder.buildFloor(i / 10);
}
}
return builder.getResult();
}
}
客户端代码
@Test
public void test() {
ResidenceBuilder rb = new ResidenceBuilder();
Designer designer1 = new Designer(rb);
Building building = designer1.build();
building.show();
Building highBuilding = designer1.buildHigh();
highBuilding.show();
}
结果输出
住宅房间:[1号房间, 2号房间, 3号房间, 4号房间];楼层:[1层, 2层]。
住宅房间:[1号房间, 2号房间, 3号房间,... 100号房间];楼层:[1层, 2层, 3层, ...10层]。
作为 Director 的设计师规定了建筑建设的复杂过程,用户无需知道细节便可以得到住宅建筑和高层住宅建筑两种产品。
如果需要对建设的造价进行统计,可以新建一个统计造价的 CountingBuilder ,将这个 CountingBuilder 作为参数传给设计师,则可以方便的得到我们想要的结果,代码如下
// 建筑造价
public class CountingBuilding implements Building {
private double countingRooms;
private double countingFloors;
public CountingBuilding() {
this.countingRooms = 0;
this.countingFloors = 0;
}
@Override
public void addRooms(String room) {
countingRooms += Double.parseDouble(room);
}
@Override
public void addFloors(String floor) {
countingFloors += Double.parseDouble(floor);
}
@Override
public List<String> getRooms() {
return null;
}
@Override
public List<String> getFloors() {
return null;
}
@Override
public void show() {
System.out.println("造价为:" + (countingRooms + countingFloors));
}
}
// 统计造价的财务人员(属于另一种类型建筑工人)
public class CountingBuilder implements Builder {
private Building building;
public CountingBuilder() {
this.building = new CountingBuilding();
}
@Override
public void buildRoom(int n) {
if (n < 10) {
building.addRooms(85.2 + "");
} else if (10 <= n && n < 50) {
building.addRooms(62.2 + "");
} else {
building.addRooms(48.7 + "");
}
}
@Override
public void buildFloor(int m) {
if (m < 4) {
building.addFloors(245.0 + "");
} else if (4 <= m && m < 12) {
building.addFloors(278.0 + "");
} else {
building.addFloors(297.0 + "");
}
}
@Override
public Building getResult() {
return building;
}
}
客户端代码
@Test
public void test() {
ResidenceBuilder rb = new ResidenceBuilder();
Designer designer1 = new Designer(rb);
Building building = designer1.build();
building.show();
Building highBuilding = designer1.buildHigh();
highBuilding.show();
CountingBuilder cb = new CountingBuilder();
Designer designer2 = new Designer(cb);
Building count = designer2.build();
count.show();
Building highCount = designer2.buildHigh();
highCount.show();
}
结果输出
住宅房间:[1号房间, 2号房间, 3号房间, 4号房间];楼层:[1层, 2层]。
住宅房间:[1号房间, 2号房间, 3号房间,... 100号房间];楼层:[1层, 2层, 3层, ...10层]。
造价为:830.8
造价为:8419.499999999989
在bean里面创建一个 静态 builder 方法 和一个 静态内部 Builder 类 ,通过调用静态 builder 方法来创建 Builder类,然后通过 Builder 类中的 build 方法直接创建一个 Bean,是简化的建造者模式
public class Student {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public static StudentBuilder builder() {
return new StudentBuilder();
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public static class StudentBuilder {
private String name;
private Integer age;
public StudentBuilder name(String name) {
this.name = name;
return this;
}
public StudentBuilder age(Integer age) {
this.age = age;
return this;
}
public Student build() {
Student student = new Student();
student.setName(this.name);
student.setAge(this.age);
return student;
}
}
}
客户端
@Test
public void testChain(){
Student student = Student.builder().name("张三").age(18).build();
System.out.println(student.toString());
}
结果输出
Student{name='张三', age=18}
在建造者模式里,有个指导者,由指导者来管理建造者,用户是与指导者联系的,指导者联系建造者最后得到产品。即建造模式可以强制实行一种分步骤进行的构造过程。工厂模式是将对象的全部创建过程封装在工厂类中,由工厂类想客户端提供最终的产品。而在建造者模式中,建造者类一般只提供产品类中各个组件的建造,而将具体建造过程交付给指导者,由指导者负责将各个组件按照特定的规则组建为产品,然后将组建好的产品交付给客户端。
github源码地址