建造者模式
建造者模式也属于创建型模式,它提供了一种创建对象的最佳方式。
定义:将一个复杂对象的构造与它的表示分离,使得同样的构建过程可以创建不同的表示。
主要解决:在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
假设此时我们需要建造一栋房子,一系列步骤简化为:
- 地基
- 钢筋工程
- 铺电线
- 粉刷
为了盖好这一栋房子,我们需要找到一个“建筑公司”或是“承包商(指挥者)”,承包商会指挥工人(具体建造者)过来造房子(产品),等待房子盖完,最后进行验收。
抽象的Builder类:
public abstract class Builder {
abstract void BuildA(); // 地基
abstract void BuildB(); // 钢筋工程
abstract void BuildC(); // 铺电线
abstract void BuildD(); // 粉刷
abstract Product getProduct();
}
具体的产品(Product)类:
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) { BuildA = buildA; }
public String getBuildB() { return BuildB; }
public void setBuildB(String buildB) { BuildB = buildB; }
public String getBuildC() { return BuildC; }
public void setBuildC(String buildC) { BuildC = buildC; }
public String getBuildD() { return BuildD; }
public void setBuildD(String buildD) { BuildD = buildD; }
@Override
public String toString() {
return "Product{" +
"BuildA='" + BuildA + '\'' +
", BuildB='" + BuildB + '\'' +
", BuildC='" + BuildC + '\'' +
", BuildD='" + BuildD + '\'' +
'}';
}
}
具体的Builder类:
public class Worker extends Builder {
private Product product;
public Worker() {
product = new Product();
}
@Override
void BuildA() {
product.setBuildA("地基");
System.out.println("地基");
}
@Override
void BuildB() {
product.setBuildB("钢筋工程");
System.out.println("钢筋工程");
}
@Override
void BuildC() {
product.setBuildC("铺电线");
System.out.println("铺电线");
}
@Override
void BuildD() {
product.setBuildD("粉刷");
System.out.println("粉刷");
}
@Override
Product getProduct() {
return product;
}
}
指挥者(Director)类:
public class Directot {
public Product build(Builder builder) {
builder.BuildA();
builder.BuildB();
builder.BuildC();
builder.BuildD();
return builder.getProduct();
}
}
测试类:
public class Test {
public static void main(String[] args) {
Directot directot = new Directot();
Product product = directot.build(new Worker());
System.out.println(product.toString());
}
}
上述例子讲解的是Builder模式的常规用法,指挥者类Director在Builder模式中具有很重要的作用,它用于指导具体构建者如何构建产品,控制调用先后次序,并向调用者返回完整的产品类,但是有些时候需要简化一下系统,也就是说,可以把Director和抽象建造者进行结合。
我们可以通过静态内部类的方式实现零件无序装配构造,这汇使用方式更加灵活,更加符合定义。
当内部有复杂对象的默认实现,使用时可以根据用户需求自由定义更改内容,并且无需改变具体的构造方式,就可以生产出不同的复杂产品。例如:麦当劳的套餐,服务员(具体建造者)可以随意搭配任意几种产品组合成一种套餐,推送给消费者。
抽象的Builder类:
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();
}
具体的产品(Product)类:
public class Product {
private String BuildA = "汉堡";
private String BuildB = "薯条";
private String BuildC = "可乐";
private String BuildD = "鸡块";
public void setBuildA(String buildA) {
BuildA = buildA;
}
public void setBuildB(String buildB) {
BuildB = buildB;
}
public void setBuildC(String buildC) {
BuildC = buildC;
}
public void setBuildD(String buildD) {
BuildD = buildD;
}
@Override
public String toString() {
return "Product{" +
"BuildA='" + BuildA + '\'' +
", BuildB='" + BuildB + '\'' +
", BuildC='" + BuildC + '\'' +
", BuildD='" + BuildD + '\'' +
'}';
}
}
具体的Builder类:
public class Worker extends Builder {
private Product product;
public Worker() {
product = new Product();
}
@Override
Builder BuildA(String msg) {
product.setBuildA(msg);
return this;
}
@Override
Builder BuildB(String msg) {
product.setBuildB(msg);
return this;
}
@Override
Builder BuildC(String msg) {
product.setBuildC(msg);
return this;
}
@Override
Builder BuildD(String msg) {
product.setBuildD(msg);
return this;
}
@Override
Product getProduct() {
return product;
}
}
测试类:
public class Test {
public static void main(String[] args) {
Worker worker = new Worker();
// 链式编程
Product product = worker.BuildA("甜品").getProduct();
System.out.println(product.toString());
}
}
建造者模式的优点:
- 产品的建造和表示分离,实现了解耦,使用建造者模式可以使客户端不必知道产品内部组成的细节
- 将复杂产品的创建步骤分解在不同的方法中,使得创新过程更加清晰
- 具体的建造者类之间是相互独立的,这有利于系统的扩展,增加新的具体建造者无需修改原有库存的代码,符合开闭原则
缺点:
-
建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不
适合使用建造者模式,因此使用范围将会受到一定的限制
-
如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大
应用场景:
- 需要生成的产品对象有复杂的内部结构,这些产品对象具备共性;
- 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
- 适合于一个具有较多的零件(属性)的产品(对象)的创建过程。
建造者与抽象工厂模式的比较:
- 与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产
品,这些产品位于不同的产品等级结构构成了一个产品族 - 在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,
客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装
过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象 - 如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车
组装工厂,通过对部件的组装可以返回一辆完整的汽车