建造者模式(
Builder Pattern
) 又叫生成器模式,建造者模式可以将一个产品的内部表象与产品的生产过程抽象出来,从而可以使同一个建造过程生成具有不同的内部表象的产品对象。当用户使用的时候只需要指定建造对象的类型就可以得到该对象,而无须知道具体的实现细节。
开闭原则
;下面我就将使用建造者模式来抽象出一个汽车工厂可以分别建造奥迪和奔驰牌的汽车,不管是奔驰还是奥迪,它们都有发动机(Engine
)、变速箱(Gearbox
)、底盘(Chassis
)等三大件,它们分别有自己的建造者类来控制自己的生产过程;
Engine
)、变速箱(Gearbox
)、底盘(Chassis
)等三大件public class Engine {
private String name;
public Engine(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Gearbox {
private String name;
public Gearbox(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Chassis {
private String name;
public Chassis(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Engine
)、变速箱(Gearbox
)、底盘(Chassis
)三个组件public class Car {
private Engine engine; // 发动机
private Gearbox gearbox; // 变速箱
private Chassis chassis; // 底盘
public Engine getEngine() {
return engine;
}
public void setEngine(Engine engine) {
this.engine = engine;
}
public Gearbox getGearbox() {
return gearbox;
}
public void setGearbox(Gearbox gearbox) {
this.gearbox = gearbox;
}
public Chassis getChassis() {
return chassis;
}
public void setChassis(Chassis chassis) {
this.chassis = chassis;
}
}
public abstract class CarBuilder {
/**
* 建造汽车发动机
*
* @return
*/
public abstract void builderEngine();
/**
* 建造汽车变速箱
*
* @return
*/
public abstract void builderGearbox();
/**
* 建造汽车底盘
*
* @return
*/
public abstract void builderChassis();
/**
* 建造汽车
*
* @return
*/
public abstract Car builderCar();
}
public interface ICarDirectory {
/**
* 建造汽车
*
* @return
*/
Car constructCar(CarBuilder builder);
}
public class CarDirectory implements ICarDirectory {
@Override
public Car constructCar(CarBuilder builder) {
// 建造发动机
builder.builderEngine();
// 建造变速箱
builder.builderGearbox();
// 建造底盘
builder.builderChassis();
return builder.builderCar();
}
}
public class AudiCarBuilder extends CarBuilder {
private Car car;
public AudiCarBuilder(){
this.car = new Car();
}
@Override
public void builderEngine() {
car.setEngine(new Engine("奥迪牌发动机"));
}
@Override
public void builderGearbox() {
car.setGearbox(new Gearbox("奥迪牌变速箱"));
}
@Override
public void builderChassis() {
car.setChassis(new Chassis("奥迪牌底盘"));
}
@Override
public Car builderCar() {
return car;
}
}
public class BenzCarBuilder extends CarBuilder {
private Car car;
public BenzCarBuilder(){
this.car = new Car();
}
@Override
public void builderEngine() {
car.setEngine(new Engine("奔驰牌发动机"));
}
@Override
public void builderGearbox() {
car.setGearbox(new Gearbox("奔驰牌变速箱"));
}
@Override
public void builderChassis() {
car.setChassis(new Chassis("奔驰牌底盘"));
}
@Override
public Car builderCar() {
return car;
}
}
public class Test {
public static void main(String[] args) {
ICarDirectory directory = new CarDirectory();
Car benzCar = directory.constructCar(new BenzCarBuilder());
System.out.println(benzCar.getEngine().getName());
System.out.println(benzCar.getGearbox().getName());
System.out.println(benzCar.getChassis().getName());
Car audiCar = directory.constructCar(new AudiCarBuilder());
System.out.println(audiCar.getEngine().getName());
System.out.println(audiCar.getGearbox().getName());
System.out.println(audiCar.getChassis().getName());
}
}
这样我们就实现了相同的生产线,可以分别生产不同品牌的汽车产品
上面演示了建造者模式的常规用法,指挥者(Director
)用来控制建造者(Builder
)的生产过程,并返回建造的产品;
下面我来演示另外一种用法,就是当一个构造方法需要传入很多参数,创建找个对象实例的时候,很容易因为参数的位置,导致最终的数据有偏差,代码可读性也很差。这个时候我们就可以利用建造者模式进行代码重构,此处的演示使用Lombok的Builder组件也可达到相同的效果:
public class Person {
private String name;
private String age;
private String sex;
public Person(String name, String age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person("小明","23","男");
}
}
public class Person {
private String name;
private String age;
private String sex;
public Person(Builder builder) {
this.name = builder.name;
this.age = builder.age;
this.sex = builder.sex;
}
public static final class Builder {
private String name;
private String age;
private String sex;
public Builder() {}
public Builder name(String val) {
name = val;
return this;
}
public Builder age(String val) {
age = val;
return this;
}
public Builder sex(String val) {
sex = val;
return this;
}
public Person build() {
return new Person(this);
}
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person.Builder().name("小明").age("20").sex("男").build();
}
}