原理
建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。
分类
建造者模式有两种分类,一种是常规的有建造指挥者的,一种没有指挥者。
代码示例
常规的建造者(有指挥者)
例子过程中我会建造一辆小汽车
产品类即小汽车
/**
* 小汽车类
*/
public class Car {
//小车的框架
private String frame;
//小车的轮胎
private String wheel;
//小车的座位
private String seat;
public String getFrame() {
return frame;
}
public void setFrame(String frame) {
this.frame = frame;
}
public String getWheel() {
return wheel;
}
public void setWheel(String wheel) {
this.wheel = wheel;
}
public String getSeat() {
return seat;
}
public void setSeat(String seat) {
this.seat = seat;
}
@Override
public String toString() {
return "{" +
"frame='" + frame + '\'' +
", wheel='" + wheel + '\'' +
", seat='" + seat + '\'' +
'}';
}
}
抽象建造者 这个类是一个通用的汽车建造的类,汽车总算是有框架、轮子、座位,但是不局限于小汽车,也可以是货车。继续扩展的话,createCar()方法就得改造成一个返回一个汽车接口或者抽象类,这里为了方便举例子,就返回一个小汽车。
/**
* 汽车抽象AbstractBuilder
*/
public abstract class AbstractBuilder {
abstract void buildFrame();
abstract void buildWheel();
abstract void buildSeat();
abstract Car createCar();
}
小汽车的实际建造者。这个建造者的目的就是组装一个产品的各个部分,并返回一个完整的产品
/**
* @date 2020/9/30 10:38
* 小汽车的具体建造者
*/
public class CarBuilder extends AbstractBuilder {
private Car car = new Car();
@Override
void buildFrame() {
System.out.println("小汽车的框架建造完成");
car.setFrame("小汽车的框架");
}
@Override
void buildWheel() {
System.out.println("小汽车的轮胎建造完成");
car.setWheel("小汽车的轮胎");
}
@Override
void buildSeat() {
System.out.println("小汽车的座位建造完成");
car.setSeat("小汽车的座位");
}
@Override
Car createCar() {
return car;
}
}
指挥者类 可以理解成小汽车生产组的组长,监督生产流程,先做哪一步,最后做哪一步,返回一个合格的产品
/**
* @author White Lee
* @date 2020/9/30 10:40
* 小汽车建造者的组长 指挥者
*/
public class Director {
private AbstractBuilder builder;
public Director(AbstractBuilder builder) {
this.builder = builder;
}
public Car getCar() {
builder.buildFrame();
builder.buildSeat();
builder.buildWheel();
return builder.createCar();
}
}
测试类
public class Test {
public static void main(String[] args) {
//具体的建造者 用于生产小汽车的建造者
//例如想生产货车,就使用货车的建造者实现抽象建造者接口AbstractBuilder即可
CarBuilder carBuilder = new CarBuilder();
//生产线的组长负责指挥生产车辆
Car car = new Director(carBuilder).getCar();
System.out.println("小汽车建造完成:" + car);
//结果展示
//小汽车的框架建造完成
//小汽车的座位建造完成
//小汽车的轮胎建造完成
//小汽车建造完成:{frame='小汽车的框架', wheel='小汽车的轮胎', seat='小汽车的座位'}
}
}
无指挥者建造者
小汽车类
/**
* 小汽车类
*/
public class Car {
//小车的框架
private String frame;
//小车的轮胎
private String wheel;
//小车的座位
private String seat;
public String getFrame() {
return frame;
}
public void setFrame(String frame) {
this.frame = frame;
}
public String getWheel() {
return wheel;
}
public void setWheel(String wheel) {
this.wheel = wheel;
}
public String getSeat() {
return seat;
}
public void setSeat(String seat) {
this.seat = seat;
}
@Override
public String toString() {
return "{" +
"frame='" + frame + '\'' +
", wheel='" + wheel + '\'' +
", seat='" + seat + '\'' +
'}';
}
}
抽象建造类
/**
* 汽车抽象AbstractBuilder
*/
public abstract class AbstractBuilder {
abstract AbstractBuilder buildFrame(String frame);
abstract AbstractBuilder buildWheel(String wheel);
abstract AbstractBuilder buildSeat(String seat);
abstract Car build();
}
实际建造者
/**
* @author White Lee
* @date 2020/9/30 10:38
* 小汽车的具体建造者
*/
public class CarBuilder extends AbstractBuilder {
private Car car = new Car();
@Override
AbstractBuilder buildFrame(String frame) {
System.out.println("小汽车的框架建造完成");
car.setFrame(frame);
return this;
}
@Override
AbstractBuilder buildWheel(String wheel) {
System.out.println("小汽车的轮胎建造完成");
car.setWheel(wheel);
return this;
}
@Override
AbstractBuilder buildSeat(String seat) {
System.out.println("小汽车的座位建造完成");
car.setSeat(seat);
return this;
}
@Override
Car build() {
return car;
}
}
测试类
public class Test {
public static void main(String[] args) {
CarBuilder carBuilder = new CarBuilder();
Car build = carBuilder.buildFrame("框架")
.buildSeat("座位")
.buildWheel("轮胎")
.build();
System.out.println("小汽车建造完成" + build);
//演示结果
//小汽车的框架建造完成
//小汽车的座位建造完成
//小汽车的轮胎建造完成
//小汽车建造完成{frame='框架', wheel='轮胎', seat='座位'}
}
}
这两种建造者的区别,第一种常规的适用于产品的属性特别多的情况,非常规范的建造流程,对生产对象的过程用户无感知;第二种适用于属性偏少的情况,用户可以自定义建造对象的属性值。Mybatis逆向工程生成的example里面就用的第二种建造条件对象。