建造者模式简介
定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。用户只需指定需要建造的类型就可以得到它们,而具体的建造的过程和细节无需知道。
UML结构图
- Builder:抽象建造类(或接口),抽象方法含有两部分,一部分是各个组件设置赋值的方法,另外一个是带返回值(具体产品类Product)的方法。
- ConcreteBuilder:具体建造类,继承于Builder类,实现了抽象类定义的所有方法,同时返回一个已创建好的Product具体对象。
- Product:具体产品类,定义各个组件的属性(实体类)。
- Director:导演类,负责安排各个组件创建顺序。
建造者模式的实现
使用步骤
- 定义具体产品类Product。
- 定义抽象建造Builder类,也可以用接口来定义,其中含有Product类属性赋值方法,另外需定义一个带Product类的返回值方法。
- 定义具体建造类,继承于抽象建造类,实现类抽象类中的所有方法,并返回一个创建好的Product对象,需要依赖于Product类,一般Product类的实例化是在成员变量初始化,或者在构造函数中初始化。
- 定义导演类,导演类没有过多的要求,只负责各个组件的创建顺序,最后返回一个具体Product对象。
- 使用者调用,先实现具体建造类,再把该对象传入导演类中。
以上就是建造者模式常规步骤。
例子
下面以造汽车为例子,汽车一般分为四大组成部分,分别是发动机、底盘、车身、电子设备。
1、定义具体产品Cart类,成员变量分为发动机、底盘、车身、电子设备。
/**
*
* @author 13480
* 具体产品类,定义各个零部件属性变量
*/
public class Cart {
//发动机
private String mEngine;
//底盘
private String mChassis;
//车身
private String mCarBody;
//电子设备
private String mERP;
public void setmEngine(String mEngine) {
this.mEngine = mEngine;
}
public void setmChassis(String mChassis) {
this.mChassis = mChassis;
}
public void setmCarBody(String mCarBody) {
this.mCarBody = mCarBody;
}
public void setmERP(String mERP) {
this.mERP = mERP;
}
}
2、创建抽象建造Builder类,定义发动机、底盘、车身、电子设备部件创建方法,以及各个部件组装成的成品create方法。
/**
*
* @author 13480
* 抽象建造者类(也可用接口定义):主要分为两部分方法构成
* 一部分:就是各个零部件的创建 的方法
* 另外一部分:把各个零部件组成成成品 的方法
*/
public abstract class Builder {
//创建发动机
public abstract void buildEngine(String engine);
//创建底盘
public abstract void buildChassis(String chassis);
//创建车身
public abstract void buildCarBody(String carBody);
//创建电子设备
public abstract void buildERP(String erp);
//集成各个组件组装成汽车
public abstract Cart create();
}
3、定义具体建造类,继承于Builder类,比如现在造一辆比亚迪汽车和长安汽车。
---------------------------比亚迪----------------
public class BYDCartBuilder extends Builder{
private Cart mCar=new Cart();
@Override
public void buildEngine(String engine) {
mCar.setmEngine(engine);
}
@Override
public void buildChassis(String chassis) {
mCar.setmChassis(chassis);
}
@Override
public void buildCarBody(String carBody) {
mCar.setmCarBody(carBody);
}
@Override
public void buildERP(String erp) {
mCar.setmERP(erp);
}
@Override
public Cart create() {
return mCar;
}
}
-------------------------------长安汽车--------------
public class ChangAnCarBuilder extends Builder{
private Cart mCar=new Cart();
@Override
public void buildEngine(String engine) {
mCar.setmEngine(engine);
}
@Override
public void buildChassis(String chassis) {
mCar.setmChassis(chassis);
}
@Override
public void buildCarBody(String carBody) {
mCar.setmCarBody(carBody);
}
@Override
public void buildERP(String erp) {
mCar.setmERP(erp);
}
@Override
public Cart create() {
return mCar;
}
}
4、定义导演类统一组装过程
/**
*
* @author 13480
* 统一组装类(指挥类):可以简单理解是一个工具类,用来操作具体产品类
* 主要的作用是规范流程,比如先组装底盘,还是发动机等等
*/
public class Director {
private Builder mBuilder;
public Director(Builder mBuilder) {
this.mBuilder = mBuilder;
}
/**
* 规范制造流程
*/
public Cart createCar(String chassis,String engine,String erp,String carBody){
mBuilder.buildChassis(chassis);
mBuilder.buildEngine(engine);
mBuilder.buildERP(erp);
mBuilder.buildCarBody(carBody);
return mBuilder.create();
}
}
5、使用者调用
public class Test {
public static void main(String[] args) {
//组装比亚迪汽车
BYDCartBuilder bydCarBuilder = new BYDCartBuilder();
//组装长安汽车
ChangAnCarBuilder changAnCarBuilder = new ChangAnCarBuilder();
Director director1 = new Director(bydCarBuilder);
Director director2 = new Director(changAnCarBuilder);
Cart createCar = director1.createCar("比亚迪底盘", "发动机", "电子设备", "车身");
Cart createCar2 = director2.createCar("长安底盘", "发动机", "电子设备", "车身");
}
}
使用场景及优缺点
优点
- 可以把复杂实现逻辑封装起来,使用者无需知道内部实现细节。
- 由于每个具体建造者类是相互独立的,没有任何关联,因此可以针对不同建造类实现不同功能,体现了扩展的特性。
缺点
- 会产生很多Builder类和导演类。
使用场景
其实根据优点就大概知道使用场景,一般是用于某些参数设置比较多的场景或者内部逻辑比较复杂,比如说封装图片加载框架,图片加载需设置的参数比较多,占位图、预加载图、错误图、缓存策略、加载样式……
改进
针对建造者模式的缺点,可以稍微改进点,可以把具体建造者类和导演类进行合并,减少了导演类的定义,如下:
扫描二维码关注公众号,回复:
1749269 查看本文章
public class BYDCart {
private BYDCartBuilder mBuilder;
public BYDCart() {
mBuilder=new BYDCartBuilder();
}
public Cart createCart(String chassis,String engine,String erp,String carBody){
mBuilder.buildChassis(chassis);
mBuilder.buildEngine(engine);
mBuilder.buildERP(erp);
mBuilder.buildCarBody(carBody);
return mBuilder.create();
}
class BYDCartBuilder extends Builder{
private Cart mCar=new Cart();
@Override
public void buildEngine(String engine) {
mCar.setmEngine(engine);
}
@Override
public void buildChassis(String chassis) {
mCar.setmChassis(chassis);
}
@Override
public void buildCarBody(String carBody) {
mCar.setmCarBody(carBody);
}
@Override
public void buildERP(String erp) {
mCar.setmERP(erp);
}
@Override
public Cart create() {
return mCar;
}
}
}