Menu
CoddyTech

建造者模式

本课属于 Coddy Java 学习旅程的“面向对象编程”单元。第 67 课,共 87 课。

构建器模式是一种创建型设计模式,用于解决一个常见问题:如何构造包含许多可选参数的复杂对象。你无需创建多个构造函数,也无需为未使用的参数传入 null,而是可以通过 Builder 一步步构造对象。

考虑创建一个包含必需字段(姓名、电子邮件)和可选字段(年龄、电话、地址)的 User 对象。如果不使用 Builder,你就需要使用层叠构造函数,或者编写一个包含许多参数的混乱构造函数。Builder 模式提供了一种更简洁的方法:

public class User {
    private final String name;    // 必填
    private final String email;   // 必填
    private final int age;        // 可选
    private final String phone;   // 可选
    
    private User(UserBuilder builder) {
        this.name = builder.name;
        this.email = builder.email;
        this.age = builder.age;
        this.phone = builder.phone;
    }
    
    public static class UserBuilder {
        private final String name;
        private final String email;
        private int age;
        private String phone;
        
        public UserBuilder(String name, String email) {
            this.name = name;
            this.email = email;
        }
        
        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }
        
        public UserBuilder phone(String phone) {
            this.phone = phone;
            return this;
        }
        
        public User build() {
            return new User(this);
        }
    }
}

Builder 的方法会返回 this,从而支持方法链式调用:这是一种流畅、易读的对象构造方式。

User user = new User.UserBuilder("Alice", "alice@email.com")
    .age(25)
    .phone("555-1234")
    .build();

注意,User 构造函数是私有的:只能通过 Builder 创建对象。当对象有许多可选字段时,这种模式特别有用,能让代码比使用很长的参数列表更易读,也更不容易出错。

challenge icon

挑战

简单

让我们使用 Builder Pattern 构建一个披萨订购系统!你不必使用一个包含几十个参数、用于设置所有可能配料和选项的构造函数,而是创建一个流畅的构建器,让披萨定制变得清晰易读。

你需要将代码分成两个文件:

  • Pizza.java:创建一个使用 Builder Pattern 构造对象的 Pizza 类。披萨应包含以下字段:

    size(String):必需,表示披萨尺寸

    cheese(boolean):可选,默认值为 false

    pepperoni(boolean):可选,默认值为 false

    mushrooms(boolean):可选,默认值为 false

    Pizza 构造函数应设为 private,并且只接受 PizzaBuilder 作为参数,将构建器中的所有值复制到披萨的字段中。

    添加一个 getDescription() 方法,返回以下格式的字符串:[size] Pizza with: [toppings],其中 toppings 是一个逗号分隔的列表,列出值为 true 的配料(Cheese、Pepperoni、Mushrooms)。如果没有选择配料,配料部分应显示为 no toppings。

    创建一个静态内部类 PizzaBuilder,其中包含:

    • 一个接受必需的 size 参数的构造函数
    • cheese()、pepperoni() 和 mushrooms() 方法,每个方法都会将对应的布尔值设为 true,并返回 this,以便链式调用
    • 一个返回新建 Pizza 的 build() 方法
  • Main.java:演示如何使用披萨构建器!你会收到 4 个输入:披萨尺寸(String),以及 3 个 yes/no 值(String),分别表示是否添加奶酪、意大利辣香肠和蘑菇。

    使用给定的尺寸创建一个 PizzaBuilder。然后,根据每个 yes/no 输入,链式调用对应的配料方法。如果输入是 "yes",就调用对应的配料方法;如果是 "no",则跳过该方法。最后,调用 build() 创建披萨。

    打印对创建完成的披萨调用 getDescription() 后得到的结果。

你会依次收到 4 个输入:尺寸(String)、是否添加奶酪(String:"yes" 或 "no")、是否添加意大利辣香肠(String:"yes" 或 "no")、是否添加蘑菇(String:"yes" 或 "no")。

例如,输入为 Large、yes、no、yes 时,输出应为:Large Pizza with: Cheese, Mushrooms

注意,Builder Pattern 让你可以构建配料任意组合的披萨,而不需要为每种可能的组合单独创建构造函数!

亲手试试

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 读取输入
        String size = scanner.nextLine();
        String addCheese = scanner.nextLine();
        String addPepperoni = scanner.nextLine();
        String addMushrooms = scanner.nextLine();
        
        // TODO:用给定的尺寸创建 PizzaBuilder
        // TODO:根据 yes/no 输入,链式调用添加配料的方法
        // TODO:构建披萨并打印其描述
        
    }
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Java 在线编译器