目录

建造者模式 (Builder Pattern)

分步骤构建复杂对象,使构建过程更加灵活清晰

概述

建造者模式是一种创建型设计模式,它允许你分步骤创建复杂对象。该模式使你能够使用相同的创建代码生成不同类型和形式的对象。

适用场景

  • 对象构造复杂,参数众多
  • 需要创建不同表示的同类对象
  • 构造过程需要分步骤执行

基础实现

代码示例

// 产品类
public class Computer {
    private String cpu;
    private String ram;
    private String storage;
    private String gpu;
    private boolean hasWifi;
    private boolean hasBluetooth;
    
    // 私有构造方法
    private Computer(Builder builder) {
        this.cpu = builder.cpu;
        this.ram = builder.ram;
        this.storage = builder.storage;
        this.gpu = builder.gpu;
        this.hasWifi = builder.hasWifi;
        this.hasBluetooth = builder.hasBluetooth;
    }
    
    // Getters...
    
    // 建造者类
    public static class Builder {
        private String cpu;
        private String ram;
        private String storage;
        private String gpu;
        private boolean hasWifi;
        private boolean hasBluetooth;
        
        public Builder cpu(String cpu) {
            this.cpu = cpu;
            return this;
        }
        
        public Builder ram(String ram) {
            this.ram = ram;
            return this;
        }
        
        public Builder storage(String storage) {
            this.storage = storage;
            return this;
        }
        
        public Builder gpu(String gpu) {
            this.gpu = gpu;
            return this;
        }
        
        public Builder hasWifi(boolean hasWifi) {
            this.hasWifi = hasWifi;
            return this;
        }
        
        public Builder hasBluetooth(boolean hasBluetooth) {
            this.hasBluetooth = hasBluetooth;
            return this;
        }
        
        public Computer build() {
            return new Computer(this);
        }
    }
}

// 使用
Computer computer = new Computer.Builder()
    .cpu("Intel i9")
    .ram("32GB")
    .storage("1TB SSD")
    .gpu("RTX 4090")
    .hasWifi(true)
    .hasBluetooth(true)
    .build();

使用 Lombok 简化

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class User {
    private Long id;
    private String username;
    private String email;
    private String phone;
    private Integer age;
    private String address;
}

// 使用
User user = User.builder()
    .id(1L)
    .username("john")
    .email("john@example.com")
    .age(25)
    .build();

带校验的建造者

public class User {
    private final String username;
    private final String email;
    private final Integer age;
    
    private User(Builder builder) {
        this.username = builder.username;
        this.email = builder.email;
        this.age = builder.age;
    }
    
    public static class Builder {
        private String username;
        private String email;
        private Integer age;
        
        public Builder username(String username) {
            this.username = username;
            return this;
        }
        
        public Builder email(String email) {
            this.email = email;
            return this;
        }
        
        public Builder age(Integer age) {
            this.age = age;
            return this;
        }
        
        public User build() {
            validate();
            return new User(this);
        }
        
        private void validate() {
            if (username == null || username.isEmpty()) {
                throw new IllegalStateException("用户名不能为空");
            }
            if (email == null || !email.contains("@")) {
                throw new IllegalStateException("邮箱格式不正确");
            }
            if (age == null || age < 0 || age > 150) {
                throw new IllegalStateException("年龄不合法");
            }
        }
    }
}

框架中的应用

StringBuilder

// JDK 中的建造者模式
String result = new StringBuilder()
    .append("Hello")
    .append(" ")
    .append("World")
    .toString();

Stream.Builder

// Stream API 中的建造者
Stream<String> stream = Stream.<String>builder()
    .add("a")
    .add("b")
    .add("c")
    .build();

Spring ResponseEntity

// Spring 的 ResponseEntity 建造者
ResponseEntity<User> response = ResponseEntity
    .status(HttpStatus.OK)
    .header("X-Custom-Header", "value")
    .body(user);

Retrofit/OkHttp Request

// OkHttp 的请求建造者
Request request = new Request.Builder()
    .url("https://api.example.com/users")
    .header("Authorization", "Bearer token")
    .get()
    .build();

实际应用:SQL 查询构造器

public class SqlQuery {
    private String select;
    private String from;
    private String where;
    private String orderBy;
    private Integer limit;
    
    private SqlQuery(Builder builder) {
        this.select = builder.select;
        this.from = builder.from;
        this.where = builder.where;
        this.orderBy = builder.orderBy;
        this.limit = builder.limit;
    }
    
    public String toSql() {
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT ").append(select)
           .append(" FROM ").append(from);
        if (where != null) {
            sql.append(" WHERE ").append(where);
        }
        if (orderBy != null) {
            sql.append(" ORDER BY ").append(orderBy);
        }
        if (limit != null) {
            sql.append(" LIMIT ").append(limit);
        }
        return sql.toString();
    }
    
    public static class Builder {
        private String select = "*";
        private String from;
        private String where;
        private String orderBy;
        private Integer limit;
        
        public Builder select(String... columns) {
            this.select = String.join(", ", columns);
            return this;
        }
        
        public Builder from(String table) {
            this.from = table;
            return this;
        }
        
        public Builder where(String condition) {
            this.where = condition;
            return this;
        }
        
        public Builder orderBy(String column) {
            this.orderBy = column;
            return this;
        }
        
        public Builder limit(int limit) {
            this.limit = limit;
            return this;
        }
        
        public SqlQuery build() {
            if (from == null) {
                throw new IllegalStateException("FROM 不能为空");
            }
            return new SqlQuery(this);
        }
    }
}

// 使用
SqlQuery query = new SqlQuery.Builder()
    .select("id", "username", "email")
    .from("users")
    .where("age > 18")
    .orderBy("created_at DESC")
    .limit(10)
    .build();

System.out.println(query.toSql());
// SELECT id, username, email FROM users WHERE age > 18 
// ORDER BY created_at DESC LIMIT 10

链式调用 vs 多参数构造

方式代码示例可读性
多参数构造new User("john", "john@e.com", 25, ...)
Setter多行 set 调用一般
建造者.username("john").email("...")

优缺点

优点缺点
代码可读性强需要额外创建 Builder 类
参数清晰明确代码量增加
支持默认值不适用于简单对象
可分步构造
线程安全(不可变对象)

最佳实践

  1. 参数较多时使用:通常超过 4-5 个参数建议使用
  2. 结合 Lombok:减少样板代码
  3. 添加参数校验:在 build() 方法中校验
  4. 创建不可变对象:适合建造者模式