第六章_建造者模式
1.介绍
1.1定义
建造者模式,即==使用多个简单的对象一步一步构建成一个复杂的对象==
1.2解决的问题
1.3使用场景
1.4应用实例
1.5角色
2.举例
2.1产品
// 产品类,定义产品的三个部分
public class Product {
private Object part1;
private Object part2;
private Object part3;
public void setPart1(Object part1) {
this.part1 = part1;
}
public void setPart2(Object part2) {
this.part2 = part2;
}
public void setPart3(Object part3) {
this.part3 = part3;
}
@Override
public String toString() {
return "Product{" +
"part1=" + part1 +
", part2=" + part2 +
", part3=" + part3 +
'}';
}
}
2.2抽象建造者
// 抽象建造者类,构建了一个产品对象,并定义了构建产品三个部分所需要的三个方法以及获取产品的方法
public abstract class Builder {
protected Product product = new Product();
public abstract void buildPart1();
public abstract void buildPart2();
public abstract void buildPart3();
public abstract Product getProduct();
}
2.3具体建造者
// 具体建造者 1
public class ConcreteBuilder1 extends Builder{
@Override
public void buildPart1() {
product.setPart1("builder 1 set part 1.");
}
@Override
public void buildPart2() {
product.setPart2("builder 1 set part 2.");
}
@Override
public void buildPart3() {
product.setPart3("builder 1 set part 3.");
}
@Override
public Product getProduct() {
System.out.println("builder 1 build product.");
return product;
}
}
// 具体建造者 2
public class ConcreteBuilder2 extends Builder {
@Override
public void buildPart1() {
product.setPart1("builder 2 set part 1.");
}
@Override
public void buildPart2() {
product.setPart2("builder 2 set part 2.");
}
@Override
public void buildPart3() {
product.setPart3("builder 2 set part 3.");
}
@Override
public Product getProduct() {
System.out.println("builder 2 build product.");
return product;
}
}
2.4指挥者对象
// 指挥者对象
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public Product construct() {
builder.buildPart1();
builder.buildPart2();
builder.buildPart3();
Product product = builder.getProduct();
return product;
}
}
2.5调用方
public static void main(String[] args) {
//调用方通过调用指挥者(传入的建造者不同,则创建的过程不一样)来创建产品,屏蔽了创建产品的过程
Director director1 = new Director(new ConcreteBuilder1());
Product product1 = director1.construct();
System.out.println(product1);
System.out.println("==================================");
Director director2 = new Director(new ConcreteBuilder2());
Product product2 = director2.construct();
System.out.println(product2);
}
2.6测试结果
builder 1 build product.
Product{part1=builder 1 set part 1., part2=builder 1 set part 2., part3=builder 1 set part 3.}
==================================
builder 2 build product.
Product{part1=builder 2 set part 1., part2=builder 2 set part 2., part3=builder 2 set part 3.}
3.实例
3.1产品
public class Car {
private String brand;
private String color;
private String engineType;
public Car(String brand, String color, String engineType) {
this.brand = brand;
this.color = color;
this.engineType = engineType;
}
// 省略 getter 和 setter 方法
}
3.2抽象建造者
public abstract class CarBuilder {
protected Car car;
public void createCar() {
car = new Car();
}
public abstract void buildBrand();
public abstract void buildColor();
public abstract void buildEngineType();
public Car getCar() {
return car;
}
}
3.3具体建造者
public class SedanCarBuilder extends CarBuilder {
@Override
public void buildBrand() {
car.setBrand("Sedan");
}
@Override
public void buildColor() {
car.setColor("Red");
}
@Override
public void buildEngineType() {
car.setEngineType("Gasoline");
}
}
public class SUVCarBuilder extends CarBuilder {
@Override
public void buildBrand() {
car.setBrand("SUV");
}
@Override
public void buildColor() {
car.setColor("Blue");
}
@Override
public void buildEngineType() {
car.setEngineType("Diesel");
}
}
3.4指挥者对象
public class CarDirector {
private CarBuilder carBuilder;
public CarDirector(CarBuilder carBuilder) {
this.carBuilder = carBuilder;
}
public void constructCar() {
carBuilder.createCar();
carBuilder.buildBrand();
carBuilder.buildColor();
carBuilder.buildEngineType();
}
public Car getCar() {
return carBuilder.getCar();
}
}
3.5调用方
public class Main {
public static void main(String[] args) {
CarBuilder sedanCarBuilder = new SedanCarBuilder();
CarDirector sedanCarDirector = new CarDirector(sedanCarBuilder);
sedanCarDirector.constructCar();
Car sedanCar = sedanCarDirector.getCar();
System.out.println(sedanCar);
CarBuilder suvCarBuilder = new SUVCarBuilder();
CarDirector suvCarDirector = new CarDirector(suvCarBuilder);
suvCarDirector.constructCar();
Car suvCar = suvCarDirector.getCar();
System.out.println(suvCar);
}
}
3.6测试结果
Car{brand='Sedan', color='Red', engineType='Gasoline'}
Car{brand='SUV', color='Blue', engineType='Diesel'}
4.源码应用
4.1StringBuilder类
JDK 中的建造者模式使用最多的就是 StringBuilder 类
StringBuilder 继承自 AbstractStringBuilder,而我们每次在调用 append 方法的时候就是在往 AbstractStringBuilder 类中变量 value 中追加字符
所以此时 AbstractStringBuilder 就对应抽象建造者,StringBuilder 就是具体的建造者,String 对象就是我们所需要的产品。但是此时我们并没有发现 Director,其实此时的 StringBuilder 类同时也充当着 Director 的角色,其 toString() 方法就是返回最终 String 对象。
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value;
/**
* The count is the number of characters used.
*/
int count;
……
@Override
public AbstractStringBuilder append(char c) {
ensureCapacityInternal(count + 1);
value[count++] = c;
return this;
}
……
}
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
……
@Override
public StringBuilder append(char c) {
super.append(c);
return this;
}
}
……
@Override
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
}
4.2Lombook中的@Bulider
我们在使用 Lombok 时有个基础注解叫 @Builder,使用该注解的类就不用再 new 对象,直接赋值然后调用 build() 方法便能构建对象。其原理就是在使用该注解的类中生成一个静态的内部 Builder类,然后通过调用该内部类的方法给生成的类对象赋值。我们以 Computer 类为例,代码如下:
@Builder
public class Computer {
private String CPU;
private String GPU;
private String memory;
private String motherboard;
private String hardDisk;
}
对代码进行编译后,再看最后生成的代码如下:
public class Computer {
private String CPU;
private String GPU;
private String memory;
private String motherboard;
private String hardDisk;
Computer(String CPU, String GPU, String memory, String motherboard, String hardDisk) {
this.CPU = CPU;
this.GPU = GPU;
this.memory = memory;
this.motherboard = motherboard;
this.hardDisk = hardDisk;
}
public static Computer.ComputerBuilder builder() {
return new Computer.ComputerBuilder();
}
public static class ComputerBuilder {
private String CPU;
private String GPU;
private String memory;
private String motherboard;
private String hardDisk;
ComputerBuilder() {
}
public Computer.ComputerBuilder CPU(String CPU) {
this.CPU = CPU;
return this;
}
public Computer.ComputerBuilder GPU(String GPU) {
this.GPU = GPU;
return this;
}
public Computer.ComputerBuilder memory(String memory) {
this.memory = memory;
return this;
}
public Computer.ComputerBuilder motherboard(String motherboard) {
this.motherboard = motherboard;
return this;
}
public Computer.ComputerBuilder hardDisk(String hardDisk) {
this.hardDisk = hardDisk;
return this;
}
public Computer build() {
return new Computer(this.CPU, this.GPU, this.memory, this.motherboard, this.hardDisk);
}
public String toString() {
return "Computer.ComputerBuilder(CPU=" + this.CPU + ", GPU=" + this.GPU + ", memory=" + this.memory + ", motherboard=" + this.motherboard + ", hardDisk=" + this.hardDisk + ")";
}
}
}
5.与工厂模式对比
建造者模式将对象的创建过程和表现分离,并且调用方通过指挥者调用方法对对象进行构建,使得调用方不再关心对象构建过程,构建对象的具体过程可以根据传入类型的不同而改变。通常在实际开发应用中通常会对建造者模式的角色进行阉割,往往只保留真正构建对象的过程。那么有的人就可能会有疑问了,构建者模式最终是获取一个对象,工厂模式也是获取一个对象,这两种模式有什么区别呢?这两种模式都是属于创建型模式,而这两种模式的侧重点不太一样:
6.优缺点
优点:
缺点: