定义和作用
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
在用户不知道对象创建过程和细节的情况下就可以直接创建复杂的对象
常规的方式
抽象构建者 Builder
//抽象的建造者 : 不负责建造 只是负责定义一些方法与接口
public abstract class Builder {
abstract void bulidA(); //地基
abstract void bulidB(); //钢筋工程
abstract void bulidC(); //铺电线
abstract void bulidD(); //粉刷
//做完上面的步骤之后会生成一个产品
abstract Product getproduct();
}
产品Produce
// 产品 做完地基 钢筋水泥 电线 粉刷后生成的产品
public class Product {
private String buildA;
private String buildB;
private String buildC;
private String buildD;
public String getBuildA() {
return buildA;
}
public void setBuildA(String buildA) {
this.buildA = buildA;
}
public String getBuildB() {
return buildB;
}
public void setBuildB(String buildB) {
this.buildB = buildB;
}
public String getBuildC() {
return buildC;
}
public void setBuildC(String buildC) {
this.buildC = buildC;
}
public String getBuildD() {
return buildD;
}
public void setBuildD(String buildD) {
this.buildD = buildD;
}
@Override
public String toString() {
return "Product{" +
"buildA='" + buildA + '\'' +
", buildB='" + buildB + '\'' +
", buildC='" + buildC + '\'' +
", buildD='" + buildD + '\'' +
'}';
}
}
具体的建造者:工人 Worker
/具体的建造者:工人
public class Worker extends Builder{
//工人需要完成一个产品
private Product product;
//产品是由工人创建的(而不是通过构造器传入)
public Worker() {
product = new Product();
}
@Override
void bulidA() {
// 创建产品 Product实现了Builder(抽象创建者)的抽象方法
product.setBuildA("地基");
System.out.println("地基");
}
@Override
void bulidB() {
product.setBuildB("钢筋工程");
System.out.println("钢筋工程");
}
@Override
void bulidC() {
product.setBuildC("铺电线");
System.out.println("铺电线");
}
@Override
void bulidD() {
product.setBuildD("粉刷");
System.out.println("粉刷");
}
@Override
Product getproduct() {
return product;
}
}
指挥 :核心 Director
//指挥: 核心 负责指挥构建一个工程 工程如何构建由他决定
public class Director {
//指挥者负责指挥他安装顺序生成一个产品(核心构建顺序)
//指挥一个抽象建造者(builder可能传入不同的工人)
public Product build(Builder builder){
builder.bulidA();
builder.bulidB();
builder.bulidC();
builder.bulidD();
return builder.getproduct();
}
}
测试类 TestBuilder
public class TestBuilder {
public static void main(String[] args) {
//指挥
Director director = new Director();
//指挥具体的工人完成产品
Product build = director.build(new Worker());
System.out.println(build.toString());
}
}
上面的实例建造者模式常规用法,导演类在建造者模式很重要,指挥具体建造者如何建造产品,导演类来决定建造顺序并返回完整产品,工人负责建造。
优化版本
我们可以通过静态内部类方式实现零件无序装配构造,这种方式更加灵活。内部有复杂对象的默认实现,使用时可以根据用户需求自由更改内容,而且不用改变构造方式。
建造者:Builder
//建造者
public abstract class Builder {
//为了方便用户传入需求 定义一些参数。若不赋值参数 就是默认Produce的套餐
abstract Builder bulidA(String msg); //汉堡
abstract Builder bulidB(String msg); //可乐
abstract Builder bulidC(String msg); //薯条
abstract Builder bulidD(String msg); //甜点
//固定 建造者模式就是为了建造产品 只是建造这些产品的时候可能出现一些默认值
abstract Product getProduct();
}
产品 : Produce
//产品: 具体的套餐
public class Product {
//固定套餐
private String buildA="汉堡"; //给上默认值 不自定义就是这个
private String buildB="可乐";
private String buildC="薯条";
private String buildD="甜点";
//自己选择套餐
public void setBuildA(String buildA) {
this.buildA = buildA;
}
public void setBuildB(String buildB) {
this.buildB = buildB;
}
public void setBuildC(String buildC) {
this.buildC = buildC;
}
public void setBuildD(String buildD) {
this.buildD = buildD;
}
@Override
public String toString() {
return "Product{" +
"buildA='" + buildA + '\'' +
", buildB='" + buildB + '\'' +
", buildC='" + buildC + '\'' +
", buildD='" + buildD + '\'' +
'}';
}
}
具体建造者: Worker
//具体建造者
public class Worker extends Builder{
Product product;
public Worker() {
product = new Product();
}
//work.buildA 返回的是Builder 可以继续调用build* .getproduct
@Override
Builder bulidA(String msg) {
product.setBuildA(msg);
return this;
}
@Override
Builder bulidB(String msg) {
product.setBuildB(msg);
return this;
}
@Override
Builder bulidC(String msg) {
product.setBuildC(msg);
return this;
}
@Override
Builder bulidD(String msg) {
product.setBuildD(msg);
return this;
}
@Override
Product getProduct() {
return product;
}
}
测试一:默认情况
public class BuilderChainTest {
public static void main(String[] args) {
//服务员
Worker worker = new Worker();
Product product = worker.getProduct();
System.out.println(product.toString());
}
}
测试二:链式编程 自定义内容
public class BuilderChainTest {
public static void main(String[] args) {
//服务员
Worker worker = new Worker();
//链式编程:在原来的基础上可以自由组合了,如果不组合也有默认的套餐
//work.buildA 返回的是Builder 可以继续调用build* 然后 .getproduct
Product product = worker.bulidA("三明治").bulidB("雪碧")
.getProduct();
System.out.println(product.toString());
}
}
总结:
优点:
- 建造者模式用户不知道产品内部组成细节
- 具体的建造者之间相互独立,有利于系统扩展,增加新的具体建造者无需要修改原有类库的代码
缺点:
- 产品具有共同点,组成部分相似。如果产品差异性大,则不适合,适用范围有限
- 如果产品内部复杂,可能导致定义很多类,系统庞大。
适用场景:
- 需要生成的产品对象有复杂的内部结构且具有共性
- 隔离复杂对象创建和适用,相同创建过程可以创建不同产品
- 适用于较多零件(属性)的产品(对象)创建过程