建造者模式(Builder Pattern)是一种创建型设计模式,它允许通过逐步构造复杂对象的方式来对其进行解耦。在建造者模式中,一个构建器类(Builder)提供了创建具有多个可选部件和复杂内部结构对象的方法,而且允许用户只通过指定必要的参数来定制对象,而无需关心对象的内部组装细节。
建造者模式的主要角色包括:
-
Product(产品类): 表示要创建的复杂对象,包含多个组成部件。它定义了产品的共性接口,包含所有产品的共有属性和方法。
-
Builder(抽象建造者): 提供了一个抽象接口,规定了创建产品对象的各个步骤,具体包括定义了一系列的方法,用于创建产品的各个部分。它是一个抽象类或者是接口,一般来说会有
buildPartX()
方法,用于构建产品的不同部分。 -
ConcreteBuilder(具体建造者): 实现了抽象建造者接口,具体定义了如何创建产品的各个部分,以及最后如何组装成一个完整的产品。在建造过程中,每个具体建造者都会跟踪产品的当前状态。
-
Director(导演类): (可选角色)负责协调建造者对象的构建过程。它不用知道具体建造者的内部细节,只知道如何通过调用建造者的接口方法来一步步指导产品的创建过程。导演类可以用来隔离客户代码和具体建造者之间的关系。
建造者模式的主要优点:
- 封装性:将对象的构造过程与表示相分离,用户只需指定复杂对象的类型和内容,无需关心其内部构造细节。
- 可扩展性:增加新的产品类型时,只需要增加新的具体建造者类,不影响已有代码。
- 灵活性:通过改变建造者的不同组合,可以创建不同表现形式的产品对象。
使用场景:
- 当构造过程复杂,有多个可选步骤或选项,不同的选项会导致创建不同的产品对象。
- 需要生成的产品对象有复杂的内部结构,这些对象的组成部分相互依赖。
- 需要独立地或按步骤创建对象,以避免一次性创建可能导致的错误或异常情况。
例如,在创建一个复杂的配置对象时,可以使用建造者模式,允许用户逐个设置各个属性,最后一步生成整个配置对象。在Java中,建造者模式可以用来构建一个不可变对象,确保对象一旦创建就不能被修改,提高了代码的健壮性和安全性。
下面是一个简单的Java实现建造者模式的例子,我们将会创建一个披萨(Pizza)的产品类,并定义一个抽象建造者(Builder)来构建披萨的不同部分,然后创建一个具体的建造者实现来制作不同口味的披萨,最后通过导演(Director)类来指导建造过程。
// 产品类:披萨
public class Pizza {
private String dough;
private String sauce;
private List<String> toppings;
// 构造函数私有化,不允许外部直接实例化
private Pizza(String dough, String sauce, List<String> toppings) {
this.dough = dough;
this.sauce = sauce;
this.toppings = toppings;
}
// 获取披萨的信息
public void describe() {
System.out.println("Dough: " + dough);
System.out.println("Sauce: " + sauce);
System.out.println("Toppings: " + toppings);
}
// 抽象建造者
public abstract static class PizzaBuilder {
protected Pizza pizza;
public PizzaBuilder() {
pizza = new Pizza("", "", new ArrayList<>());
}
// 建造面团
public abstract void buildDough(String dough);
// 建造酱料
public abstract void buildSauce(String sauce);
// 添加配料
public abstract void addTopping(String topping);
// 获取最终产品
public Pizza getPizza() {
return pizza;
}
}
// 具体建造者:意大利风味披萨建造者
public static class ItalianPizzaBuilder extends PizzaBuilder {
@Override
public void buildDough(String dough) {
pizza.setDough(dough);
}
@Override
public void buildSauce(String sauce) {
pizza.setSauce(sauce);
}
@Override
public void addTopping(String topping) {
pizza.getToppings().add(topping);
}
}
// 导演类
public static class PizzaDirector {
public Pizza constructPizza(PizzaBuilder builder) {
// 指导建造过程
builder.buildDough("Italian Dough");
builder.buildSauce("Tomato Sauce");
builder.addTopping("Mozzarella Cheese");
builder.addTopping("Pepperoni");
return builder.getPizza();
}
}
// 客户端代码
public static void main(String[] args) {
PizzaBuilder builder = new ItalianPizzaBuilder();
PizzaDirector director = new PizzaDirector();
// 使用导演类来构建披萨
Pizza pizza = director.constructPizza(builder);
// 描述并展示披萨
pizza.describe();
}
}
在这个例子中,ItalianPizzaBuilder
是具体建造者,实现了构建披萨各部分的方法;PizzaDirector
则是导演类,它通过调用建造者的方法来完成披萨的创建。这样,客户端代码仅需要与导演类交互,就可以方便地创建出特定口味的披萨。
补充
建造者模式和抽象工厂模式区别
建造者模式(Builder Pattern)和抽象工厂模式(Abstract Factory Pattern)都是创建型设计模式,它们都用于创建对象,但两者关注点和使用场景有所不同:
建造者模式:
- 关注点:建造者模式主要用于构建复杂对象的各个部分,一步一步创建一个具有多个可选部件的复杂对象。它的重点在于一步步构建产品的过程,强调的是逐步构造一个产品,通常会返回一个不可变的产品实例。
- 结构:通常包含一个抽象建造者接口,一个或多个具体建造者类,以及一个产品类。
- 场景:当对象的构建过程需要分步进行,或者构建过程十分复杂,对象的不同部分可以有不同的排列组合时,建造者模式能有效隔离构建过程和具体产品对象,使得产品构建过程更为灵活。
抽象工厂模式:
- 关注点:抽象工厂模式关注的是提供一个接口,用于创建一族相关或相互依赖的对象,而不指定具体类。它强调的是创建一系列相关或互相依赖的产品族,而非单一产品。
- 结构:包含一个抽象工厂接口/抽象类,以及多个具体工厂类,以及一系列的产品接口/抽象类和具体产品类。
- 场景:当系统需要创建一系列相关的对象,且客户端需要使用这些对象,但不需要知道具体实现时,抽象工厂模式就能提供一套标准的创建接口,使得客户端可以根据工厂来获取不同产品族的产品。
总结区别:
- 目标:建造者模式专注于构建一个复杂的单个对象,而抽象工厂模式侧重于创建一组相关的产品对象。
- 关注点:建造者模式关注对象构建步骤和顺序,抽象工厂模式关注的是提供不同产品簇的选择和创建。
- 粒度:建造者模式创建的是单个对象的多个组成部分,抽象工厂模式创建的是多个不同但相关联的对象。
举个例子:
- 建造者模式就像是一个汽车装配线,按照一定的顺序和规则,逐步安装发动机、轮胎、内饰等部件,最后得到一辆完整的汽车。
- 抽象工厂模式更像是汽车品牌的生产线,能够生产宝马品牌的各种车型(轿车、SUV、跑车等),同时还生产与这些车型配套的零部件(宝马轮胎、宝马座椅等)。