1.定义
将复杂对象的构建与表示分离,使得可以使用相同的构建过程创建不同的表示。
2.使用场景
1、需要生成的对象具有复杂的内部结构。 2、需要生成的对象内部属性本身相互依赖。
例如:1、去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐"。 2、JAVA 中的 StringBuilder。
3.实现
/**
* 产品类(Product):多个部件组成的复杂对象,由具体建造者来创建其各个零部件。
* @author Administrator
*
*/
public class Car {
private String frame;
private String seat;
public String getFrame() {
return frame;
}
public void setFrame(String frame) {
this.frame = frame;
}
public String getSeat() {
return seat;
}
public void setSeat(String seat) {
this.seat = seat;
}
}
/**
* 抽象建造者类(Builder):这个接口规定要实现包含创建产品各个子部件的抽象方法以及返回复杂产品的方法,并不涉及具体的部件对象的创建。
* @author Administrator
*
*/
public abstract class Builder {
protected Car car = new Car();
abstract void buildFrame();
abstract void buildSeat();
abstract Car createCar();
}
/**
* 具体建造者类(ConcreteBuilder):实现抽象 Builder 定义的所有方法,并且返回一个装配好的对象。
* @author Administrator
*
*/
public class ACarBuilder extends Builder{
@Override
void buildFrame() {
// TODO Auto-generated method stub
car.setFrame("铝合金车架");
}
@Override
void buildSeat() {
// TODO Auto-generated method stub
car.setSeat("真皮座椅");
}
@Override
Car createCar() {
// TODO Auto-generated method stub
return car;
}
}
/**
* 具体建造者类(ConcreteBuilder):实现抽象 Builder 定义的所有方法,并且返回一个装配好的对象。
* @author Administrator
*
*/
public class BCarBuilder extends Builder{
@Override
void buildFrame() {
// TODO Auto-generated method stub
car.setFrame("不锈钢车架");
}
@Override
void buildSeat() {
// TODO Auto-generated method stub
car.setSeat("布艺座椅");
}
@Override
Car createCar() {
// TODO Auto-generated method stub
return car;
}
}
/**
* 指挥者类(Director):负责安排已有模块的顺序,然后调用 Builder 建造产品。
* @author Administrator
*
*/
public class Director {
public Car construct(Builder builder) {
builder.buildFrame();
builder.buildSeat();
return builder.createCar();
}
}
/**
* 测试类
* @author Administrator
*
*/
public class Test {
public static void main(String[] args) {
Director director = new Director();
Car aCar = director.construct(new ACarBuilder());
System.out.println(aCar.getFrame()+" "+aCar.getSeat());
System.out.println("=============================");
Car bCar = director.construct(new BCarBuilder());
System.out.println(bCar.getFrame()+" "+bCar.getSeat());
}
}
运行结果
4.简化建造者使用
如果一个类中有很多属性,为了避免构造函数的参数列表过长,影响代码的可读性和易用性,我们可以通过构造函数配合set()方法来解决。但是,如果存在下面情况中的任意一种,我们就要考虑使用建造者模式了。
1、我们把类的必填属性放到构造函数中,强制创建对象的时候就设置。如果必填的属性有很多,把这些必填属性都放到构造函数中设置,那构造函数就又会出现参数列表很长的问题。如果我们把必填属性通过set()方法设置,那校验这些必填属性是否已经填写的逻辑就无处安放了。
2、如果类的属性之间有一定的依赖关系或者约束条件,我们继续使用构造函数配合set()方法的设计思路,那这些依赖关系或约束条件的校验逻辑就无处安放了。
3、如果我们希望创建不可变对象,也就是说,对象在创建好之后,就不能再修改内部的属性值,要实现这个功能,我们就不能在类中暴露set()方法。构造函数配合set()方法来设置属性值的方式就不适用了。
/**
* 产品类(Vehicle):多个部件组成的复杂对象,由具体建造者来创建其各个零部件。
* 汽车的组成一般是由发动机、底盘、车身和电气设备等四个基本部分组成,以及一些顶窗、记录仪等可有可无的部分。
* @author Administrator
*
*/
public class Vehicle {
private String engine;//发动机
private String chassis;//底盘
private String body;//车身
private String electricalEquipment;//电气设备
private String transomWindow;//顶窗
private String recorder;//记录仪
private Vehicle(Builder builder) {
this.engine = builder.engine;
this.chassis = builder.chassis;
this.body = builder.body;
this.electricalEquipment = builder.electricalEquipment;
this.transomWindow = builder.transomWindow;
}
/**
* 建造者类:实现包含创建产品各个子部件的方法并且返回一个装配好的对象。
*/
public static class Builder {
private String engine;//发动机
private String chassis;//底盘
private String body;//车身
private String electricalEquipment;//电气设备
private String transomWindow;//顶窗
private String recorder;//记录仪
public Builder setBody(String body) {
this.body = body;
return this;
}
public Builder setChassis(String chassis) {
this.chassis = chassis;
return this;
}
public Builder setElectricalEquipment(String electricalEquipment) {
this.electricalEquipment = electricalEquipment;
return this;
}
public Builder setEngine(String engine) {
this.engine = engine;
return this;
}
public Builder setRecorder(String recorder) {
this.recorder = recorder;
return this;
}
public Builder setTransomWindow(String transomWindow) {
this.transomWindow = transomWindow;
return this;
}
public Vehicle build() {
if(engine==null||body==null||chassis==null||electricalEquipment==null) {
throw new IllegalArgumentException("参数不足");
}
return new Vehicle(this);
}
}
}
/**
* 测试类
* @author Administrator
*
*/
public class Client {
public static void main(String[] args) {
Vehicle vehicle = new Vehicle.Builder()
.setBody("body")
.setChassis("chassis")
.setEngine("engine")
.setElectricalEquipment("electricalEquipment")
.build();
System.out.println("=================================");
Vehicle vehicle1 = new Vehicle.Builder()
.setBody("body1")
.setChassis("chassis1")
.setEngine("engine1")
.build();
}
}
运行结果
5.总结
主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
优点: 1、建造者独立,易扩展。 2、便于控制细节风险。
缺点: 1、产品必须有共同点,范围有限制。 2、如内部变化复杂,会有很多的建造类。