【Java 设计模式 · 创建型】建造者模式(Builder Pattern)

创建型模式:关注对象的创建过程,它描述如何将对象的创建、使用分离,让用户无需关心对象的创建细节,从而降低系统的耦合度,让设计方案易于修改、扩展。

一、概述

建造者模式(Builder Pattern,生成器模式):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

二、结构

  • Builder(抽象建造者):
    创建产品对象部件的指定抽象接口,在接口中声明构建各种部件(属性)的方法,与返回复杂对象的方法。
  • ConcreteBuilder(具体建造者):
    实现了 Builder 接口,实现了各个部件的具体构造和装配方法,定义并明确创建的复杂对象,也可以由它提供一个方法返回复杂对象。
  • Product(产品):
    被构建的复杂对象,包含多个组成部件,具体建造者创建该产品内部,并定义装配过程。
  • Director(指挥者):
    又称 导演类,负责安排复杂对象的构建次序,指挥者与抽象建造者之间的存在关系,通过 construct() 方法调用部件构造、装配方法,完成建造。可以通过反射、配置文件实现,灵活建造者可省去指挥者,但用户须为部件构建方法传入合适的参数。

三、举例实现

实例代码:
Product(产品):

public class Car {
	//定义部件,可以是值类型 / 引用类型
	private String engine;		//引擎
	private String wheel;		//轮胎
	private String accelerator;	//油门
	private String clutch;		//离合器
	private String shiftGear;	//变速器
	private String breakSys;	//刹车系统
	private String shell;		//外壳
	private String fuelTank;	//燃油箱
	private String seat;		//座椅
	/*
	 * 省略所有属性的 Setter、Getter 方法
	 */
}

Builder(抽象建造者):

public abstract class CarBuilder {
	//创建产品对象
	protected Car car = new Car();
	
	public abstract void buildEngine();
	public abstract void buildWheel();
	public abstract void buildAccelerator();
	public abstract void buildClutch();
	public abstract void buildShiftGear();
	public abstract void buildBreakSys();
	public abstract void buildShell();
	public abstract void buildFuelTank();
	public abstract void buildSeat();
	
	//返回产品对象
	public Car getWholeCar(){
		return car;
	}
}

ConcreteBuilder(具体建造者):

public class ConcreteCarBuilder extends CarBuilder {
	@Override
	public void buildEngine() {
		car.setEngine("高质量引擎");
	}
	@Override
	public void buildWheel(){
		car.setWheel("耐磨防滑轮胎");
	}
	@Override
	public void buildAccelerator(){
		car.setAccelerator("加速优秀油门");
	}
	@Override
	public void buildClutch(){
		car.setClutch("优质离合器");
	}
	@Override
	public void buildShiftGear(){
		car.setShiftGear("高精度变速箱");
	}
	@Override
	public void buildBreakSys(){
		car.setBreakSys("快速刹车系统");
	}
	@Override
	public void buildShell(){
		car.setbuildShell("高抗外壳");
	}
	@Override
	public void buildFuelTank(){
		car.setFuelTank("耐高温燃油箱");
	}
	@Override
	public void buildSeat(){
		car.setSeat("优质皮草座椅");
	}

Director(指挥者):

public class CarAssembler{
	private CarBuilder builder;
	//装配工:负责汽车组装,扮演Director角色
	public CarAssembler(CarBuilder builder){
		this.builder = builder;
	}
	
	//产品构建组装方法
	public Product construct(){
		builder.buildEngine();
		builder.buildWheel();
		builder.buildAccelerator();
		builder.buildClutch();
		builder.buildShiftGear();
		builder.buildBreakSys();
		builder.buildShell();
		builder.buildFuelTank();
		builder.buildSeat();
		//产品组装完成
		return builder.getWholeCar();
	}
}

四、讨论:指挥者类

指挥者类 Director 类十分重要,简单的 Director 类用于指导具体建造者如何构建产品,依次调用buildePartX() 方法,控制调用先后次序后返回完整对象。

1、省略 Director 类

为了简化系统结构,可将 Director 和 抽象建造者合并,提供逐步构建复杂产品对象的 construct() 方法。一般在抽象 Builder 类中,将该方法定义为静态 (static) 方法,便于直接调用。

传参的construct方法:

public abstract class CarBuilder{
	protected static Car car = new Car();
	
	public abstract void buildEngine();
	public abstract void buildWheel();
	public abstract void buildAccelerator();
	public abstract void buildClutch();
	public abstract void buildShiftGear();
	public abstract void buildBreakSys();
	public abstract void buildShell();
	public abstract void buildFuelTank();
	public abstract void buildSeat();

	public static Car construct(CarBuilder builder){
		builder.buildEngine();
		builder.buildWheel();
		builder.buildAccelerator();
		builder.buildClutch();
		builder.buildShiftGear();
		builder.buildBreakSys();
		builder.buildShell();
		builder.buildFuelTank();
		builder.buildSeat();
		//产品组装完成
		return car;
	}
}

无参的construct方法:

public abstract class CarBuilder{
	protected static Car car = new Car();
	
	public abstract void buildEngine();
	public abstract void buildWheel();
	public abstract void buildAccelerator();
	public abstract void buildClutch();
	public abstract void buildShiftGear();
	public abstract void buildBreakSys();
	public abstract void buildShell();
	public abstract void buildFuelTank();
	public abstract void buildSeat();

	public static Car construct(){
		this.buildEngine();
		this.buildWheel();
		this.buildAccelerator();
		this.buildClutch();
		this.buildShiftGear();
		this.buildBreakSys();
		this.buildShell();
		this.buildFuelTank();
		this.buildSeat();
		//产品组装完成
		return car;
	}
}

这里,construct() 方法定义了 buildPartX() 方法的调用次序,并为此提供了标准流程,类似于模板方法模式。

这种方式不影响可扩展性,简化了结构,但加重了建造者的职责,为更符合单一职责原则,大多数情况下并不推荐这样做。

2、引入钩子方法

建造者模式可以通过 Director 类更加精细地控制产品的创建过程,例如增加一类称为钩子方法(Hook Method) 的特殊方法来控制是否对某个buildPartX() 进行调用。

钩子方法的返回值为 boolean 类型,方法名一般为isXXX(),钩子方法定义在 抽象 Builder 类 中。

public abstract class CarBuilder{
	protected static Car car = new Car();
	
	public abstract void buildEngine();
	public abstract void buildWheel();
	public abstract void buildAccelerator();
	public abstract void buildClutch();
	public abstract void buildShiftGear();
	public abstract void buildBreakSys();
	public abstract void buildShell();
	public abstract void buildFuelTank();
	public abstract void buildSeat();
	
	//钩子方法
	public boolean isMotor(){	//是否为电动汽车
		return false;
	}
	
	public Car createCar(){
		return car;
	}
}
public class ConcreteCarBuilder extends CarBuilder {
	@Override
	public void buildEngine() {
		car.setEngine("高质量引擎");
	}
	@Override
	public void buildWheel(){
		car.setWheel("耐磨防滑轮胎");
	}
	@Override
	public void buildAccelerator(){
		car.setAccelerator("加速优秀油门");
	}
	@Override
	public void buildClutch(){
		car.setClutch("优质离合器");
	}
	@Override
	public void buildShiftGear(){
		car.setShiftGear("高精度变速箱");
	}
	@Override
	public void buildBreakSys(){
		car.setBreakSys("快速刹车系统");
	}
	@Override
	public void buildShell(){
		car.setbuildShell("高抗外壳");
	}
	@Override
	public void buildFuelTank(){
		car.setFuelTank("耐高温燃油箱");
	}
	@Override
	public void buildSeat(){
		car.setSeat("优质皮草座椅");
	}
	
	//覆盖钩子方法
	@Override
	public boolean isMotor(){	//是否为电动汽车
		return true;
	} 
}
public class CarAssembler{	
	//产品构建组装方法:传入参数,更加灵活,根据是否重写钩子方法判断是否为电动汽车
	public Product construct(CarBuilder builder){
		
		builder.buildWheel();
		builder.buildAccelerator();
		builder.buildShiftGear();
		builder.buildBreakSys();
		builder.buildShell();
		//通过钩子方法控制产品的构建
		if(!builder.isMotor()){
			builder.buildClutch();		//离合器
			builder.buildEngine();		//引擎
			builder.buildFuelTank();	//油箱
		}
		
		builder.buildSeat();
		//产品组装完成
		return builder.getWholeCar();
	}
}

五、灵活建造者 : 链式建造

灵活的建造者模式被广泛地应用在 Spring框架 中,我们熟悉的StringBuilder类也采用这一模式,灵活的建造者模式去除了指挥者类,使得用户可以参与到对象的构建过程中,但是要求用户本身对构建对象的方法有一定了解。

应用实例:

  • jdk源码中,StringBuilder类(StringBuffer类)的核心方法为我们提供了链式创建对象的方法,并通过重写 toString() 方法 返回了一个完整的String对象。
  • MyBatis中 SqlSessionFactoryBuiler 同样应用了链式建造方式创建对象。

实例代码:

Product(产品):

public class Car {
    //定义部件,可以是值类型 / 引用类型
    private String engine;		//引擎
    private String wheel;		//轮胎
    private String accelerator;	//油门
    private String clutch;		//离合器
    private String shiftGear;	//变速器
    private String breakSys;	//刹车系统
    private String shell;		//外壳
    private String fuelTank;	//燃油箱
    private String seat;		//座椅
    /*
	 * 省略所有属性的 Setter、Getter、toString 方法
	 */
}

ConcreteBuilder(具体建造者):

public class CarBuilder {
	//创建产品对象
	protected Car car = new Car();

	public CarBuilder buildEngine(String text) {
		car.setEngine(text);
		return this;
	}

	public CarBuilder buildWheel(String text) {
		car.setWheel(text);
		return this;
	}

	public CarBuilder buildAccelerator(String text) {
		car.setAccelerator(text);
		return this;
	}

	public CarBuilder buildClutch(String text) {
		car.setClutch(text);
		return this;
	}

	public CarBuilder buildShiftGear(String text) {
		car.setShiftGear(text);
		return this;
	}

	public CarBuilder buildBreakSys(String text) {
		car.setBreakSys(text);
		return this;
	}

	public CarBuilder buildShell(String text) {
		car.setShell(text);
		return this;
	}

	public CarBuilder buildFuelTank(String text) {
		car.setFuelTank(text);
		return this;
	}

	public CarBuilder buildSeat(String text) {
		car.setSeat(text);
		return this;
	}

	//返回产品对象
	public Car build(){
		return car;
	}
}

测试代码:

Car car = new CarBuilder()
        .buildAccelerator("加速优秀油门")
        .buildBreakSys("快速刹车系统")
        .buildClutch("优质离合器")
        .buildEngine("高质量引擎")
        .buildFuelTank("耐高温燃油箱")
        .buildSeat("优质皮草座椅")
        .buildShell("高抗外壳")
        .buildShiftGear("高精度变速箱")
        .buildWheel("耐磨防滑轮胎")
        .build();
System.out.println(car);

测试结果

六、特点

☯ 优点

  • 建造者模式中,用户无需关心产品内部组成细节,将产品与本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。如有需要,可以将创建过程暴露给用户,使得对象的创建更加灵活,但这对用户提出了更高的要求。
  • 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的建造者,用户使用不同的具体建造者就可得到不同的产对象。增加新的建造者无需修改原有类库代码,系统扩展方便,符合开闭原则。
  • 可以更加精细的控制产品创建过程,创建思路更加清晰。

☯ 缺点

  • 建造者模式创建产品具有较多共同点,其组成 成分相似,如若两对象组成部分相差过大,使用会受限。
  • 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统很庞大。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值