建造者模式概述
建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。。
建造者模式是一种创建型设计模式。
建造者模式又可以称为生成器模式。
建造者模式结构图
建造者模式包含如下4种角色:
(1)产品 (Product):要创建的产品类对象。
(2)建造者(Builder):建造者的抽象类,规范产品对象的各个组成部分的创建,一般由子类实现具体的创建过程。
(3)建造者实现 (Concrete Builder):根据不同的业务逻辑,具体实现产品对象的各个组成部分的创建。
(4)指导者(Director):调用具体的创建者,来创建对象的各个组成部分。
建造者模式的适用场景
(1)需要生产的产品对象有复杂的内部结构,这些产品对象具备共性。
(2)隔离复杂产品的创建和使用,并使用相同的创建过程可以创建不同的产品。
(3)适合于一个具有较多的组件的产品的创建过程。
建造者模式的优缺点
优点:
(1)产品的构造与表示分离,实现了解耦。使用建造者模式可以使客户端不必知道产品内部组成的细节。
(2)将复杂方法的创建步骤分解在不同的方法中,使得创建过程更加清晰。
(3)具体的建造者间是相互独立的,这有利于系统的扩展。增加新的具体建造者无需修改原有类库的代码,符合“开闭原则”。
缺点:
(1)建造者模式所创建的产品一般有较多的共同点,其组成部分相似,如果产品间差异较大,则不适合使用建造者模式。即建造者模式的使用范围有一定的限制。
(2)如果产品的内部变化复杂,可能需要定义很多具体的建造者来实现这种变化,导致系统变得庞大。
代码实现
为了简化其数据模型,我们将组成建筑物的模块归纳为3个组件,分别是地基、墙体、屋顶,将它们组装起来就能形成一座建筑物。
Building.java —— 建筑物
import java.util.ArrayList;
import java.util.List;
/**
* 建筑物
*/
public class Building {
// 建筑物组件
private List<String> components = new ArrayList<>();
// 地基
public void setBasement(String basement) {
this.components.add(basement);
}
// 墙体
public void setWall(String wall) {
this.components.add(wall);
}
// 屋顶
public void setRoof(String roof) {
this.components.add(roof);
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
for (int i = this.components.size() - 1; i>= 0; i--) {
sb.append(this.components.get(i));
}
return sb.toString();
}
}
Builder.java —— 施工方
/**
* 施工方
*/
public interface Builder {
// 建造地基
void buildBasement();
// 建造墙体
void buildWall();
// 建造屋顶
void buildRoof();
// 获取建筑物
Building getBuilding();
}
ApartmentBuilder.java —— 公寓施工方
/**
* 公寓施工方
*/
public class ApartmentBuilder implements Builder {
private Building apartment;
public ApartmentBuilder() {
this.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++) {
apartment.setWall("║ □ □ □ □ ║\n");
}
}
@Override
public void buildRoof() {
System.out.println("封顶,部署通风井,做防水层,保温层。");
apartment.setRoof("╔═════════╗\n");
}
@Override
public Building getBuilding() {
return this.apartment;
}
}
HouseBuilder.java —— 别墅施工方
/**
* 别墅施工方
*/
public class HouseBuilder implements Builder {
private Building house;
public HouseBuilder() {
this.house = new Building();
}
@Override
public void buildBasement() {
System.out.println("挖土方,部署管道、线缆,水泥加固,搭建围墙、花园。");
this.house.setBasement("╬╬╬╬╬╬╬╬╬\n");
}
@Override
public void buildWall() {
System.out.println("搭建木质框架,石膏板封墙并粉饰内外墙。");
this.house.setWall("|田|田|田|\n");
}
@Override
public void buildRoof() {
System.out.println("建造木质屋顶、阁楼,安装烟囱,做好防水。");
this.house.setRoof("╱◥█████◣\n");
}
@Override
public Building getBuilding() {
return this.house;
}
}
Director.java —— 工程总监
/**
* 工程总监
*/
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void setBuilder(Builder builder) {
this.builder = builder;
}
public void direct() {
System.out.println("=====工程项目启动=====");
// 第一步,打好地基
builder.buildBasement();
// 第二步,建造框架、墙体
builder.buildWall();
// 第三步,封顶
builder.buildRoof();
System.out.println("=====工程项目竣工=====");
System.out.println(builder.getBuilding());
}
}
Client.java —— 客户端
public class Client {
public static void main(String[] args) {
// 别墅施工方
Director director = new Director(new HouseBuilder());
director.direct();
// 公寓施工方
director.setBuilder(new ApartmentBuilder());
director.direct();
}
}
输出结果:
=====工程项目启动=====
挖土方,部署管道、线缆,水泥加固,搭建围墙、花园。
搭建木质框架,石膏板封墙并粉饰内外墙。
建造木质屋顶、阁楼,安装烟囱,做好防水。
=====工程项目竣工=====
╱◥█████◣
|田|田|田|
╬╬╬╬╬╬╬╬╬
=====工程项目启动=====
深挖地基,修建地下车库,部署管道、线缆、风道。
搭建多层建筑框架,建造电梯井,钢筋混凝土浇灌。
封顶,部署通风井,做防水层,保温层。
=====工程项目竣工=====
╔═════════╗
║ □ □ □ □ ║
║ □ □ □ □ ║
║ □ □ □ □ ║
║ □ □ □ □ ║
║ □ □ □ □ ║
║ □ □ □ □ ║
║ □ □ □ □ ║
║ □ □ □ □ ║
╚═════════╝