建造者模式的主要目的是将一个复杂对象的构建过程封装起来,使得客户端代码不需要知道对象创建的细节。这种模式特别适用于那些具有多个组成部分、创建过程复杂、对象属性多且大多数属性可选的场合。
在Java中,建造者模式通常涉及以下几个角色:
- Builder(建造者):为创建一个Product对象的各个部件指定抽象接口。
- ConcreteBuilder(具体建造者):实现Builder的接口以构造和装配该产品的各个部件。定义并明确它所创建的表示,并提供一个检索产品的接口。
- Director(指挥者):构造一个使用Builder接口的对象。
- Product(产品):表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。
- Client(客户端):创建一个Director对象,并用它所想要的Builder对象来配置。
以下是建造示例产品的代码:Product类表示复杂对象,Builder类是抽象建造者类,ConcreteBuilder1和ConcreteBuilder2是具体的建造者类,buildPartA;b;c用来代指构建产品的不同部分,Director类负责指挥构建过程,Client类是客户端代码。
我们用图像来表示各个类之间的关系:
先构建Product产品类:
class Product {private String partA;private String partB;private String partC;public void setPartA(String partA) {this.partA = partA;}public void setPartB(String partB) {this.partB = partB;}public void setPartC(String partC) {this.partC = partC;}public void show() {System.out.println("Product: " + partA + ", " + partB + ", " + partC);}
}
抽象建造者类:
abstract class Builder {protected Product product = new Product();public abstract void buildPartA();public abstract void buildPartB();public abstract void buildPartC();public Product getResult() {return product;}
}
具体建造者类1:
class ConcreteBuilder1 extends Builder {public void buildPartA() {product.setPartA("Part A1");}public void buildPartB() {product.setPartB("Part B1");}public void buildPartC() {product.setPartC("Part C1");}
}
具体建造者类2:
class ConcreteBuilder2 extends Builder {public void buildPartA() {product.setPartA("Part A2");}public void buildPartB() {product.setPartB("Part B2");}public void buildPartC() {product.setPartC("Part C2");}
}
指挥者类:
class Director {private Builder builder;public Director(Builder builder) {this.builder = builder;}public void construct() {builder.buildPartA();builder.buildPartB();builder.buildPartC();}
}
客户端代码:
public class BuilderPatternDemo {public static void main(String[] args) {Builder builder1 = new ConcreteBuilder1();Director director1 = new Director(builder1);director1.construct();Product product1 = builder1.getResult();product1.show();Builder builder2 = new ConcreteBuilder2();Director director2 = new Director(builder2);director2.construct();Product product2 = builder2.getResult();product2.show();}
}
适用场景
- 对象结构复杂:当一个对象有很多属性,且内部结构非常复杂时,使用建造者模式可以将这些属性的构建过程封装起来,使得客户端代码不需要直接处理这些复杂性。
- 构建步骤多:如果创建一个对象需要很多步骤,尤其是在这些步骤之间有依赖关系或者某些步骤可以省略时,建造者模式可以将这些步骤分离,使得每一步都可以独立执行,同时也允许不同的步骤组合来创建不同的对象表示。
- 创建与使用分离:在希望将对象的创建过程与它的使用过程分离时,建造者模式提供了一种机制,使得客户端代码可以在不了解对象内部细节的情况下,通过指定的步骤创建出所需的对象。
JDK中的建造者模式
- StringBuilder 类:StringBuilder 类提供了 append() 方法,允许链式调用来构建字符串。这种方式避免了多次创建字符串对象,提高了效率。StringBuilder 就是通过建造者模式来实现这一链式创建对象的过程。
- ProcessBuilder 类:ProcessBuilder 类用于创建操作系统进程。它也提供了一种流畅的接口,允许开发者通过连续调用方法来设置进程的各种属性,最后通过 start() 方法来启动进程。ProcessBuilder 的这种使用方式也是建造者模式的一个体现。
优点
- 封装性良好:建造者模式通过将复杂对象的创建过程封装在建造者类中,实现了创建过程和使用过程的分离。这样做的好处是,客户端代码不需要知道对象是如何一步步构建起来的,只需要知道如何组合这些步骤即可。这不仅使得客户端代码更加简洁,也降低了出错的可能性。
- 扩展性良好:由于建造者类之间相互独立,这在一定程度上实现了解耦。当需要增加新的构建步骤或者修改现有步骤时,只需修改相应的建造者类,而不影响其他类。这种设计提高了系统的可维护性和可扩展性。
- 简化复杂对象的创建:对于参数多、校验复杂的对象创建过程,建造者模式提供了一种清晰且易于理解的方式来逐步构建对象。这种方法特别适用于那些构造函数参数众多,或者对象创建过程需要多个步骤的情况。
- 提高代码的可读性和可维护性:建造者模式使得代码的结构更加清晰,每个建造者类负责一部分构建逻辑,这有助于提高代码的可读性和可维护性。
缺点
- 增加类的数量:为了实现复杂对象的构建,可能需要引入多个建造者类,这会增加系统中类的总数。
- 内部修改困难:如果产品类的内部结构或构建过程发生变化,可能需要修改建造者类,这可能会导致维护上的困难。
- 范围限制:建造者模式要求产品具有共同点,这限制了它的使用范围。如果产品的内部变化非常复杂,可能会导致建造者类的数量增加,从而使得系统变得更加复杂。
建造者模式和工厂模式区别
- 目的不同:建造者模式关注于创建复杂对象的构建过程,将构建过程和表示分离,以便可以逐步构建复杂对象。工厂模式关注于对象的创建,将对象的创建过程封装在工厂中,以便在客户端中使用。
- 构造过程不同:建造者模式注重的是部件构建的过程,旨在通过一步一步地精确构造创建出一个复杂的对象。工厂模式一般都是创建一个产品,注重的是把这个产品创建出来就行,只要创建出来,不关心这个产品的组成部分。