定义
建造者模式是设计模式的一种,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
模式结构
(1) Builder(抽象建造者类):为创建一个产品对象的各个部件指定抽象接口。
(2) ConcreteBuilder(具体建造者类):实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并提供一个检索产品的接口。
(3) Director(指挥者):构造一个使用Builder接口的对象。
(4) Product(产品类):表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
适用场景
1、某个对象有复杂的内部结构,通常包含多个成员属性,而且属性是可选的。
2、相同的方法,不同的执行顺序,产生不同的对象或不同的运行结果。
3、当创建一个对象需要很多步骤时,适合使用建造者模式。
代码实现
这里我们以建造房子为例来说明一下:
首先我们先构建一个建筑物类,建造一个建筑物需要地基,墙体和屋顶三个部分。
产品类:
public class Building {//建筑物
//用来模拟房子组建的堆叠
private List<String> buildingComponents = new ArrayList<>();
public void setBasement(String basement) {//地基
this.buildingComponents.add(basement);
}
public void setWall(String wall) {//墙体
this.buildingComponents.add(wall);
}
public void setRoof(String roof) {//房顶
this.buildingComponents.add(roof);
}
@Override
public String toString() {
String buildingStr = "";
for (int i = buildingComponents.size() - 1; i >= 0; i--) {
buildingStr += buildingComponents.get(i);
}
return buildingStr;
}
}
抽象建造者:
//施工方接口
public interface Builder {
public void buildBasement();
public void buildWall();
public void buildRoof();
public Building getBuilding();
}
具体建造者
// 别墅施工方
public class HouseBuilder implements Builder {
private Building house;
public HouseBuilder() {
house = new Building();
}
@Override
public void buildBasement() {
System.out.println("挖地基,部署管道、线缆,水泥加固,搭建围墙、花园。");
house.setBasement("╬╬╬╬╬╬╬╬\n");
}
@Override
public void buildWall() {
System.out.println("搭建木质框架,石膏板封墙并粉饰内外墙。");
house.setWall("|田|田 田|\n");
}
@Override
public void buildRoof() {
System.out.println("建造木质屋顶、阁楼,安装烟囱,做好防水。");
house.setRoof("╱◥███◣\n");
}
@Override
public Building getBuilding() {
return house;
}
}
// 公寓楼施工方
public class ApartmentBuilder implements Builder {
private Building apartment;
public ApartmentBuilder() {
apartment = new Building();
}
@Override
public void buildBasement() {
System.out.println("深挖地基,修建地下车库,部署管道、线缆、风道。");
apartment.setBasement("╚═════════╝\n");
}
@Override
public void buildWall() {
System.out.println("搭建多层建筑框架,建造电梯井,钢筋混凝土浇灌。");
for (int i = 0; i < 8; i++) {// 此处假设固定8层
apartment.setWall("║ □ □ □ □ ║\n");
}
}
@Override
public void buildRoof() {
System.out.println("封顶,部署通风井,做防水层,保温层。");
apartment.setRoof("╔═════════╗\n");
}
@Override
public Building getBuilding() {
return apartment;
}
}
指挥者:
//工程总监
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void setBuilder(Builder builder) {
this.builder = builder;
}
public Building direct() {
System.out.println("=====工程项目启动=====");
// 第一步,打好地基;
builder.buildBasement();
// 第二步,建造框架、墙体;
builder.buildWall();
// 第三步,封顶;
builder.buildRoof();
System.out.println("=====工程项目竣工=====");
return builder.getBuilding();
}
}
测试结果:
public class BuildTest {
public static void main(String[] args) {
//招工,建别墅。
Builder builder = new HouseBuilder();
//交给工程总监
Director director = new Director(builder);
//得到具体的建筑物
System.out.println(director.direct());
}
}
控制台打印结果:
=====工程项目启动=====
挖地基,部署管道、线缆,水泥加固,搭建围墙、花园。
搭建木质框架,石膏板封墙并粉饰内外墙。
建造木质屋顶、阁楼,安装烟囱,做好防水。
=====工程项目竣工=====
╱◥███◣
|田|田 田|
╬╬╬╬╬╬╬╬
优缺点
优点:
1、封装性,在建造者模式中,调用方不必知道产品内部组成的细节,将一个复杂对象的构建与它的表示分离,使得相同的创建过程可以创建不同的产品对象。
2、扩展性,每个具体建造者都相互独立,替换具体建造者或新增具体建造者都很便捷。
3、更关注"由零件一步一步地组装出产品对象" 。将复杂产品的创建步骤拆分到不同的方法中,使得创建过程更加清晰。
缺点:
1、建造者模式所创建的产品对象一般组成部分相似,如果产品的内部变化复杂,需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
2、如果产品内部结构发生变化,建造者也要相应修改,有较大的维护成本。