建造者模式属于创建型模式,它提供了一种创建对象的最佳方式。
定义:讲一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
主要作用:在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象
用户只需要给出复杂对象的类型和内容,建造者模式负责创建复杂对象(把内部的建造过程和细节隐藏起来)
比如举一个造房子的例子,将造房子的步骤简化为如下步骤:(1)地基(2)钢筋工程(3)铺电线(4)粉刷。如果要盖一座房子,首先要找一个建筑公司或工程承包商(指挥者)。承包商指挥工人(具体建造者)来造房子,最后验收。
1.定义一个抽象的建造者
//抽象的建造者
public abstract class builder {
abstract void buildA();//地基
abstract void buildB();//钢筋
abstract void buildC();//铺电线
abstract void buildD();//粉刷
//完工,得到产品
abstract product getProduct();
}
2.需要生成的产品
//产品:房子
public class product {
private String a;
private String b;
private String c;
private String d;
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
public String getC() {
return c;
}
public void setC(String c){
this.c=c;
}
public String getD() {
return d;
}
public void setD(String d) {
this.d = d;
}
@Override
public String toString() {
return "product{" +
"a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
", d='" + d + '\'' +
'}';
}
}
3.具体生产产品的工人
//工人:具体的建造者
public class worker extends builder{
private product product;
public worker() {
product=new product();
}
@Override
void buildA() {
product.setA("地基");
System.out.println("地基");
}
@Override
void buildB() {
product.setB("钢筋工程");
System.out.println("钢筋工程");
}
@Override
void buildC() {
product.setC("铺电线");
System.out.println("铺电线");
}
@Override
void buildD() {
product.setD("粉刷");
System.out.println("粉刷");
}
@Override
product getProduct() {
return product;
}
}
4.指挥者负责指挥工人如何构建产品
//指挥:核心。负责指挥构建一个工程,工程如何创建,由它决定
public class director {
//指挥工人按照顺序建房子
public product build(builder builder)
{
builder.buildA();
builder.buildB();
builder.buildC();
builder.buildD();
return builder.getProduct();
}
}
5.消费者使用
public class test {
public static void main(String[] args) {
//指挥
director d=new director();
//指挥具体的工人完成产品
product p = d.build(new worker());
System.out.println(p.toString());
}
}
上面的示例是Builder模式的常规用法,导演类Direct在Builder模式中具有很重要的作用,它用于指导具体构建者如何构建产品,控制调用先后次序,并向调用者返回完整的产品类,但是有些情况下需要简化系统结构,可以把Direct和抽象建造者进行结合。
通过静态内部类方式实现零件无序装配构造,这种方式使用更加灵活,更符合定义。内部有复杂对象的默认实现,使用时可以根据用户需求自由定义更改内容,并且无序改变具体的构造方式。就可以生产出不同复杂产品。
比如:麦当劳的套餐,服务员(具体建造者)可以随意搭配任意几种产品(零件)组成一款套餐(产品),然后出售给客户。比第一种方式少了指挥者,主要是因为第二种方式把指挥者交给用户来操作,使得产品的创建更加简单灵活。
1.创建一个抽象的建造者
public abstract class Builder {
abstract Builder buildA(String msg);//汉堡
abstract Builder buildB(String msg);//可乐
abstract Builder buildC(String msg);//薯条
abstract Builder buildD(String msg);//甜品
abstract Product getProduct();
}
2.创建一个产品类
public class Product {
private String A="汉堡";
private String B="可乐";
private String C="薯条";
private String D="甜品";
public String getA() {
return A;
}
public void setA(String a) {
A = a;
}
public String getB() {
return B;
}
public void setB(String b) {
B = b;
}
public String getC() {
return C;
}
public void setC(String c) {
C = c;
}
public String getD() {
return D;
}
public void setD(String d) {
D = d;
}
@Override
public String toString() {
return "Product{" +
"A='" + A + '\'' +
", B='" + B + '\'' +
", C='" + C + '\'' +
", D='" + D + '\'' +
'}';
}
}
3.创建一个具体的建造者
public class Worker extends Builder{
private Product product;
public Worker() {
product = new Product();
}
@Override
Builder buildA(String msg) {
product.setA(msg);
return this;
}
@Override
Builder buildB(String msg) {
product.setB(msg);
return this;
}
@Override
Builder buildC(String msg) {
product.setC(msg);
return this;
}
@Override
Builder buildD(String msg) {
product.setD(msg);
return this;
}
@Override
Product getProduct() {
return product;
}
}
4.消费者使用
public class Test {
public static void main(String[] args) {
Worker worker = new Worker();
//在原来的基础上可以只有组合,如果不组合,也有自己默认的值
Product product = worker
.buildA("全家桶")
.buildB("雪碧")
.getProduct();
System.out.println(product.toString());
}
}
优点:
- 产品的建造和表示分离,实现了解耦。使用建筑者模式可以使客户端不必知道产品内部组成的细节。
- 将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰
- 具体的建造者类之间相互独立,这有利于系统的扩展。增加新的具体建造者无需修改原有类库的代码,符合“开闭原则”。
缺点:
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分类似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围收到一定的限制
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化。导致系统变得很庞大。
应用场景
- 需要生成的产品对象有复杂的内部结构,这些产品对象具备共性
- 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品
- 适合于一个具有较多的零件(属性)的产品(对象)的创建过程
建造者与抽象工厂的比较
- 与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
- 在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象。
- 如果将抽象工厂模式看出配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车。