一、建造者模式简介
1.1、定义
建造者模式指将一个复杂的对象构造过程和对象的表示进行分离。使同样的建造过程可以创建不同的表示,将构建过程拆分成多个简单的对象,将不变和变进行分离。不变的是对象的组成部分,变化的是每个部分的具体内容。
比如建造汽车的过程,不变的是都需要车身、底盘、车轮、发动机等组件,变化的是每个组件可以有不同的构造过程。
1.2、优缺点
a.封装性好,构建和表示进行分离
b.扩展性好,各个具体的建造者相互独立,各个组件之间互相解耦
c.对象调用者无需关系对象的具体建造过程,满足迪米特法则
1.3、建造者模式的角色
产品:需要建造的对象,通常包含是由多个简单的组件组合成的复杂对象
抽象建造者:包含创建产品各个子部件的抽象方法的接口,通过还包含一个返回复杂对象的方法用于返回建造后的对象
具体建造者:实现抽象建造者,完成复杂产品各个子部件的具体创建
指挥者:调用建造者对象中的部件构造方法与装配方法完成复杂对象的创建,指挥者不关心具体产品的信息
二、建造者模式案例
1、业务场景
构造一个汽车对象,汽车对象包含了车身、底盘、发动机、车轮等核心组件
2、代码实现
a.定义汽车对象及各个组件的实体类
/**
* 汽车类
*/
public class Car {
//车架
private CarFrame frame;
//发动机
private Engine engine;
//底盘
private Chassis chassis;
//车轮
private Wheel wheel;
public CarFrame getFrame() {
return frame;
}
public void setFrame(CarFrame frame) {
this.frame = frame;
}
public Engine getEngine() {
return engine;
}
public void setEngine(Engine engine) {
this.engine = engine;
}
public Chassis getChassis() {
return chassis;
}
public void setChassis(Chassis chassis) {
this.chassis = chassis;
}
public Wheel getWheel() {
return wheel;
}
public void setWheel(Wheel wheel) {
this.wheel = wheel;
}
}
b.定义抽象建造者,提供返回对象的方法并定义汽车对象构建各个子部件的抽象
/**
* 抽象汽车建造者
*/
public abstract class CarBuilder {
protected Car car = new Car();
/** 返回构造的汽车对象*/
public Car builder(){
return car;
}
/** 构建车架*/
public abstract CarBuilder frame();
/** 构建发动机*/
public abstract CarBuilder engine();
/** 构建底盘*/
public abstract CarBuilder chassis();
/** 构建车轮*/
public abstract CarBuilder wheel();
}
c.实现具体的建造者,如奔驰汽车建造者
/**
* 奔驰汽车建造者实现类
*/
public class BenzCarBuilder extends CarBuilder{
@Override
public CarBuilder frame() {
System.out.println("奔驰建造者构建车轮");
car.setFrame(new CarFrame("奔驰车轮"));
return this;
}
@Override
public CarBuilder engine() {
System.out.println("奔驰建造者构建发动机");
car.setEngine(new Engine("奔驰发动机"));
return this;
}
@Override
public CarBuilder chassis() {
System.out.println("奔驰建造者构建底盘");
car.setChassis(new Chassis("奔驰底盘"));
return this; this;
}
@Override
public CarBuilder wheel() {
System.out.println("奔驰建造者构建车轮");
car.setWheel(new Wheel("奔驰车轮"));
return this;
}
}
测试代码如下:
public static void main(String[] args){
CarBuilder builder = new BenzCarBuilder();
/** 通过奔驰建造者构建汽车对象 */
Car car = builder.frame().engine().chassis().builder();
System.out.println(JSON.toJSONString(car));
}
1 奔驰建造者构建车轮
2 奔驰建造者构建发动机
3 奔驰建造者构建底盘
4 {"chassis":{"name":"奔驰底盘"},"engine":{"name":"奔驰发动机"},"frame":{"name":"奔驰车轮"}}
调用方main函数中无需关心汽车是如何构建的,只需要关心需要将哪些组件组合到汽车对象上。如果汽车需要增加或者删除一些组件,只需要在抽象建造者中增加或删除对应的方法即可,比如需要添加仪表盘组件,则只需要定义仪表盘对象,并且在抽象建造者中添加对应的方法即可,代码如下:
/**
* 抽象汽车建造者
*/
public abstract class CarBuilder {
protected Car car = new Car();
/** 返回构造的汽车对象*/
public Car builder(){
return car;
}
/** 构建车架*/
public abstract CarBuilder frame();
/** 构建发动机*/
public abstract CarBuilder engine();
/** 构建底盘*/
public abstract CarBuilder chassis();
/** 构建车轮*/
public abstract CarBuilder wheel();
/** 构建仪表盘*/
public abstract CarBuilder bashBoard();
}
此时构造汽车时就可以加上仪表盘的构造
public static void main(String[] args){
CarBuilder builder = new BenzCarBuilder();
/** 通过奔驰建造者构建汽车对象 */
Car car = builder.frame().engine().chassis().bashBoard().builder();
System.out.println(JSON.toJSONString(car));
}
另外本例子中的具体建造者是直接实现了构建细节,还可以改造成将构建细节分离,将构建的组件进行抽象化,比如将上例中的需求改动,汽车不再由奔驰建造者来建造,而是由一个第三方建造者来构建,第三方建造者造汽车时可能会用保时捷的发动机、奔驰的车身、宝马的底盘和奥迪的仪表盘,此时将构建细节交给具体建造者的化就不好扩展,所以具体建造者应该将构建组件的部分抽象分离出去。代码如下:
/**
* 车架组件
*/
public interface CarFrame {
public String name();
}
/**
* 底盘组件
*/
public interface Chassis {
public String name();
}
/**
* 发动机组件
*/
public interface Engine {
public String name();
}
/**
* 车轮组件
*/
public interface Wheel {
public String name();
}
/**
* 仪表盘抽象
*/
public interface BashBoard {
public String name();
}
修改抽象建造者类,此时由于组件是直接由外部构建,那么可以直接去除建造者类的抽象定义,直接由建造者类构建即可,代码如下:
/**
* 抽象汽车建造者
*/
public class CarBuilder {
protected Car car = new Car();
/** 返回构造的汽车对象*/
public Car builder(){
return car;
}
/** 构建车架*/
public CarBuilder frame(CarFrame carFrame){
car.setFrame(carFrame);
return this;
}
/** 构建发动机*/
public CarBuilder engine(Engine engine){
car.setEngine(engine);
return this;
}
/** 构建底盘*/
public CarBuilder chassis(Chassis chassis){
car.setChassis(chassis);
return this;
}
/** 构建车轮*/
public CarBuilder wheel(Wheel wheel){
car.setWheel(wheel);
return this;
}
/** 构建仪表盘*/
public CarBuilder bashBoard(BashBoard bashBorad){
car.setBashBoard(bashBorad);
return this;
}
}
测试代码:
public static void main(String[] args){
CarBuilder builder = new CarBuilder();
/** 通过建造者类构建汽车对象 */
Car car = builder
.frame(new BenzFrame())//奔驰车架
.engine(new PorscheEngine())//保时捷发动机
.chassis(new BmwChassis())//宝马底盘
.bashBoard(new AudiBashBoard())//奥迪仪表盘
.wheel(new MichelinWheel())//米其林车轮
.builder();
System.out.println(car.toString());
}
{"engine":"保时捷发动机","wheel":"米其林车轮","chassis":"宝马底盘","bashBoard":"奥迪仪表盘","frame":"奔驰车架"}
三、建造者模式和工厂模式的对比
1、建造者不关注组件的生产过程,只关心复杂对象的构建过程;而工厂模式需要关心各个组件的生产过程;
2、建造者倾向于建造结构相同内容不同的对象;工厂模式倾向于批量生产结构相同且内容也相同的对象;
3、建造者模式中客户端可以控制如何构造对象的组件;工厂模式中客户端无法控制构建对象的细节;
可以表示中建造者模式更加注重的是创建对象的过程;工厂模式更加注重的是创建对象的结果。