沙漏中的沙 發表於 2026-1-12 08:27:58

Java开发中StepBuilder模式详解

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>一、什么是Step Builder模式</li><ul class="second_class_ul"><li>1.1 传统Builder模式的局限性</li><li>1.2 Step Builder模式的优势</li></ul><li>二、Step Builder基础实现</li><ul class="second_class_ul"><li>2.1 简单示例:用户注册</li><li>2.2 工作原理分析</li></ul><li>三、实战案例:HTTP请求构建器</li><ul class="second_class_ul"><li>3.1 场景分析</li><li>3.2 完整实现</li></ul><li>四、开源框架中的Step Builder应用</li><ul class="second_class_ul"><li>4.1 OkHttp Request Builder分析</li><li>4.2 Spring RestTemplate增强</li></ul><li>五、高级技巧与最佳实践</li><ul class="second_class_ul"><li>5.1 泛型Step Builder</li><li>5.2 条件分支的Step Builder</li><li>5.3 验证增强</li></ul><li>六、Step Builder vs 其他模式</li><ul class="second_class_ul"><li>6.1 对比表格</li><li>6.2 选择指南</li></ul><li>七、实际生产经验</li><ul class="second_class_ul"><li>7.1 Lombok集成</li><li>7.2 测试友好性</li><li>7.3 性能考虑</li></ul><li>八、常见问题与解决方案</li><ul class="second_class_ul"><li>8.1 如何处理可选参数组</li><li>8.2 如何支持不可变对象</li><li>8.3 如何处理继承</li></ul><li>九、总结</li><ul class="second_class_ul"><li>9.1 核心优势</li><li>9.2 适用场景总结</li><li>9.3 最佳实践清单</li></ul><li>总结&nbsp;</li><ul class="second_class_ul"></ul></ul></div><p class="maodian"></p><h2>一、什么是Step Builder模式</h2>
<p class="maodian"></p><h3>1.1 传统Builder模式的局限性</h3>
<p>在Java开发中,我们经常使用Builder模式来构建复杂对象。传统的Builder模式虽然解决了构造函数参数过多的问题,但存在一个明显的缺陷:<strong>无法在编译期保证必填参数的完整性</strong>。</p>
<p><strong>传统Builder的问题示例:</strong></p>
<div class="jb51code"><pre class="brush:java;">// 传统Builder模式
public class User {
    private String username;    // 必填
    private String password;    // 必填
    private String email;       // 必填
    private String phone;       // 可选
    private Integer age;      // 可选

    public static class Builder {
      private String username;
      private String password;
      private String email;
      private String phone;
      private Integer age;

      public Builder username(String username) {
            this.username = username;
            return this;
      }

      public Builder password(String password) {
            this.password = password;
            return this;
      }

      public Builder email(String email) {
            this.email = email;
            return this;
      }

      public Builder phone(String phone) {
            this.phone = phone;
            return this;
      }

      public Builder age(Integer age) {
            this.age = age;
            return this;
      }

      public User build() {
            // 运行时检查,容易遗漏
            if (username == null || password == null || email == null) {
                throw new IllegalStateException("缺少必填字段");
            }
            return new User(this);
      }
    }
}

// 使用时可能会忘记设置必填字段
User user = new User.Builder()
    .username("john")
    // 忘记设置password和email
    .phone("123456")
    .build();// 运行时才会抛出异常!
</pre></div>
<p class="maodian"></p><h3>1.2 Step Builder模式的优势</h3>
<p>Step Builder模式(也称为Staged Builder或Telescopic Builder)通过<strong>类型系统在编译期强制要求按顺序设置必填参数</strong>,从而避免了运行时错误。</p>
<p><strong>核心思想:</strong></p>
<ul><li>每个必填参数对应一个构建步骤(Step)</li><li>每个步骤只暴露下一步需要的方法</li><li>利用接口和泛型确保类型安全</li><li>编译器强制完成所有必填步骤</li></ul>
<p><strong>Step Builder的调用流程:</strong></p>
<div class="jb51code"><pre class="brush:java;">Step 1: Username    Step 2: Password    Step 3: Email    Step 4: Build
   ↓                  ↓                   ↓                ↓
──→ ──→ ──→
                                             
                                             
</pre></div>
<p class="maodian"></p><h2>二、Step Builder基础实现</h2>
<p class="maodian"></p><h3>2.1 简单示例:用户注册</h3>
<div class="jb51code"><pre class="brush:java;">package com.example.builder;

/**
* Step Builder模式 - 用户注册示例
*/
public class User {

    private final String username;
    private final String password;
    private final String email;
    private final String phone;
    private final Integer age;

    private User(Builder builder) {
      this.username = builder.username;
      this.password = builder.password;
      this.email = builder.email;
      this.phone = builder.phone;
      this.age = builder.age;
    }

    // ============ Step Builder接口定义 ============

    /**
   * 步骤1: 设置用户名
   */
    public interface UsernameStep {
      PasswordStep username(String username);
    }

    /**
   * 步骤2: 设置密码
   */
    public interface PasswordStep {
      EmailStep password(String password);
    }

    /**
   * 步骤3: 设置邮箱
   */
    public interface EmailStep {
      BuildStep email(String email);
    }

    /**
   * 步骤4: 构建对象(可选参数)
   */
    public interface BuildStep {
      BuildStep phone(String phone);
      BuildStep age(Integer age);
      User build();
    }

    // ============ Builder实现类 ============

    private static class Builder implements UsernameStep, PasswordStep, EmailStep, BuildStep {

      private String username;
      private String password;
      private String email;
      private String phone;
      private Integer age;

      @Override
      public PasswordStep username(String username) {
            this.username = username;
            return this;
      }

      @Override
      public EmailStep password(String password) {
            this.password = password;
            return this;
      }

      @Override
      public BuildStep email(String email) {
            this.email = email;
            return this;
      }

      @Override
      public BuildStep phone(String phone) {
            this.phone = phone;
            return this;
      }

      @Override
      public BuildStep age(Integer age) {
            this.age = age;
            return this;
      }

      @Override
      public User build() {
            return new User(this);
      }
    }

    // ============ 静态工厂方法 ============

    public static UsernameStep builder() {
      return new Builder();
    }

    // Getters
    public String getUsername() { return username; }
    public String getPassword() { return password; }
    public String getEmail() { return email; }
    public String getPhone() { return phone; }
    public Integer getAge() { return age; }

    @Override
    public String toString() {
      return "User{" +
                "username='" + username + '\'' +
                ", email='" + email + '\'' +
                ", phone='" + phone + '\'' +
                ", age=" + age +
                '}';
    }
}
</pre></div>
<p><strong>使用示例:</strong></p>
<div class="jb51code"><pre class="brush:java;">public class StepBuilderDemo {

    public static void main(String[] args) {
      // ✅ 正确使用 - 编译通过
      User user1 = User.builder()
                .username("john_doe")
                .password("securePass123")
                .email("john@example.com")
                .phone("1234567890")
                .age(25)
                .build();

      System.out.println(user1);

      // ✅ 只设置必填字段
      User user2 = User.builder()
                .username("jane_doe")
                .password("password456")
                .email("jane@example.com")
                .build();

      System.out.println(user2);

      // ❌ 编译错误 - 缺少必填字段
      // User user3 = User.builder()
      //         .username("alice")
      //         .build();// 编译失败:找不到build()方法
    }
}
</pre></div>
<p class="maodian"></p><h3>2.2 工作原理分析</h3>
<div class="jb51code"><pre class="brush:java;">类型系统保证调用顺序:

User.builder()                     返回类型: UsernameStep
    ↓ 只能调用username()
.username("john")                  返回类型: PasswordStep
    ↓ 只能调用password()
.password("pass123")               返回类型: EmailStep
    ↓ 只能调用email()
.email("john@example.com")         返回类型: BuildStep
    ↓ 可以调用phone()、age()或build()
.phone("123456")                   返回类型: BuildStep
    ↓ 可以调用age()或build()
.build()                           返回类型: User
</pre></div>
<p><strong>类型安全的关键:</strong></p>
<ol><li><strong>接口链</strong>:每个步骤返回不同的接口类型</li><li><strong>单一实现</strong>:Builder类实现所有接口</li><li><strong>方法可见性</strong>:每个接口只暴露特定方法</li><li><strong>编译期检查</strong>:IDE和编译器强制按顺序调用</li></ol>
<p class="maodian"></p><h2>三、实战案例:HTTP请求构建器</h2>
<p class="maodian"></p><h3>3.1 场景分析</h3>
<p>在构建HTTP客户端时,某些参数是必需的(如URL、HTTP方法),而某些是可选的(如请求头、超时时间)。使用Step Builder可以确保必填参数不会遗漏。</p>
<p class="maodian"></p><h3>3.2 完整实现</h3>
<div class="jb51code"><pre class="brush:java;">package com.example.http;

import java.util.*;

/**
* HTTP请求构建器 - Step Builder模式
*/
public class HttpRequest {

    private final String url;
    private final HttpMethod method;
    private final Map&lt;String, String&gt; headers;
    private final String body;
    private final int timeoutSeconds;
    private final boolean followRedirects;

    public enum HttpMethod {
      GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS
    }

    private HttpRequest(Builder builder) {
      this.url = builder.url;
      this.method = builder.method;
      this.headers = Collections.unmodifiableMap(new HashMap&lt;&gt;(builder.headers));
      this.body = builder.body;
      this.timeoutSeconds = builder.timeoutSeconds;
      this.followRedirects = builder.followRedirects;
    }

    // ============ Step接口定义 ============

    public interface UrlStep {
      MethodStep url(String url);
    }

    public interface MethodStep {
      BuildStep method(HttpMethod method);
      BuildStep get();
      BuildStep post();
      BuildStep put();
      BuildStep delete();
    }

    public interface BuildStep {
      BuildStep header(String key, String value);
      BuildStep headers(Map&lt;String, String&gt; headers);
      BuildStep body(String body);
      BuildStep timeout(int seconds);
      BuildStep followRedirects(boolean follow);
      HttpRequest build();
    }

    // ============ Builder实现 ============

    private static class Builder implements UrlStep, MethodStep, BuildStep {

      private String url;
      private HttpMethod method;
      private Map&lt;String, String&gt; headers = new HashMap&lt;&gt;();
      private String body;
      private int timeoutSeconds = 30;// 默认30秒
      private boolean followRedirects = true;

      @Override
      public MethodStep url(String url) {
            if (url == null || url.trim().isEmpty()) {
                throw new IllegalArgumentException("URL不能为空");
            }
            this.url = url;
            return this;
      }

      @Override
      public BuildStep method(HttpMethod method) {
            this.method = method;
            return this;
      }

      @Override
      public BuildStep get() {
            return method(HttpMethod.GET);
      }

      @Override
      public BuildStep post() {
            return method(HttpMethod.POST);
      }

      @Override
      public BuildStep put() {
            return method(HttpMethod.PUT);
      }

      @Override
      public BuildStep delete() {
            return method(HttpMethod.DELETE);
      }

      @Override
      public BuildStep header(String key, String value) {
            this.headers.put(key, value);
            return this;
      }

      @Override
      public BuildStep headers(Map&lt;String, String&gt; headers) {
            this.headers.putAll(headers);
            return this;
      }

      @Override
      public BuildStep body(String body) {
            this.body = body;
            return this;
      }

      @Override
      public BuildStep timeout(int seconds) {
            if (seconds &lt;= 0) {
                throw new IllegalArgumentException("超时时间必须大于0");
            }
            this.timeoutSeconds = seconds;
            return this;
      }

      @Override
      public BuildStep followRedirects(boolean follow) {
            this.followRedirects = follow;
            return this;
      }

      @Override
      public HttpRequest build() {
            return new HttpRequest(this);
      }
    }

    // ============ 静态工厂方法 ============

    public static UrlStep builder() {
      return new Builder();
    }

    // ============ 执行方法 ============

    public void execute() {
      System.out.println("执行HTTP请求:");
      System.out.println("URL: " + url);
      System.out.println("Method: " + method);
      System.out.println("Headers: " + headers);
      System.out.println("Body: " + body);
      System.out.println("Timeout: " + timeoutSeconds + "s");
      System.out.println("Follow Redirects: " + followRedirects);
    }

    // Getters
    public String getUrl() { return url; }
    public HttpMethod getMethod() { return method; }
    public Map&lt;String, String&gt; getHeaders() { return headers; }
    public String getBody() { return body; }
    public int getTimeoutSeconds() { return timeoutSeconds; }
    public boolean isFollowRedirects() { return followRedirects; }
}
</pre></div>
<p><strong>使用示例:</strong></p>
<div class="jb51code"><pre class="brush:java;">public class HttpRequestDemo {

    public static void main(String[] args) {
      // GET请求
      HttpRequest getRequest = HttpRequest.builder()
                .url("https://api.example.com/users")
                .get()
                .header("Authorization", "Bearer token123")
                .header("Accept", "application/json")
                .timeout(60)
                .build();

      getRequest.execute();

      System.out.println("\n" + "=".repeat(50) + "\n");

      // POST请求
      HttpRequest postRequest = HttpRequest.builder()
                .url("https://api.example.com/users")
                .post()
                .header("Content-Type", "application/json")
                .header("Authorization", "Bearer token456")
                .body("{\"name\":\"John\",\"email\":\"john@example.com\"}")
                .timeout(30)
                .followRedirects(false)
                .build();

      postRequest.execute();

      System.out.println("\n" + "=".repeat(50) + "\n");

      // PUT请求 - 使用便捷方法
      HttpRequest putRequest = HttpRequest.builder()
                .url("https://api.example.com/users/123")
                .put()
                .headers(Map.of(
                  "Content-Type", "application/json",
                  "Authorization", "Bearer token789"
                ))
                .body("{\"name\":\"Jane\"}")
                .build();

      putRequest.execute();
    }
}
</pre></div>
<p class="maodian"></p><h2>四、开源框架中的Step Builder应用</h2>
<p class="maodian"></p><h3>4.1 OkHttp Request Builder分析</h3>
<p>虽然OkHttp的Request.Builder不是严格的Step Builder,但我们可以用Step Builder改进它:</p>
<div class="jb51code"><pre class="brush:java;">package com.example.okhttp;

import okhttp3.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
* 改进的OkHttp请求构建器
*/
public class StepOkHttpRequest {

    private final Request request;
    private final OkHttpClient client;

    private StepOkHttpRequest(Builder builder) {
      Request.Builder requestBuilder = new Request.Builder()
                .url(builder.url);

      // 设置HTTP方法和请求体
      switch (builder.method) {
            case GET:
                requestBuilder.get();
                break;
            case POST:
                requestBuilder.post(builder.requestBody);
                break;
            case PUT:
                requestBuilder.put(builder.requestBody);
                break;
            case DELETE:
                if (builder.requestBody != null) {
                  requestBuilder.delete(builder.requestBody);
                } else {
                  requestBuilder.delete();
                }
                break;
      }

      // 添加请求头
      builder.headers.forEach(requestBuilder::addHeader);

      this.request = requestBuilder.build();
      this.client = builder.client != null ? builder.client : new OkHttpClient();
    }

    public enum Method {
      GET, POST, PUT, DELETE
    }

    // ============ Step接口定义 ============

    public interface UrlStep {
      MethodStep url(String url);
    }

    public interface MethodStep {
      BuildStep get();
      BodyStep post();
      BodyStep put();
      BuildStep delete();
    }

    public interface BodyStep {
      BuildStep jsonBody(String json);
      BuildStep formBody(Map&lt;String, String&gt; formData);
      BuildStep emptyBody();
    }

    public interface BuildStep {
      BuildStep header(String name, String value);
      BuildStep client(OkHttpClient client);
      StepOkHttpRequest build();
    }

    // ============ Builder实现 ============

    private static class Builder implements UrlStep, MethodStep, BodyStep, BuildStep {

      private String url;
      private Method method;
      private RequestBody requestBody;
      private Map&lt;String, String&gt; headers = new HashMap&lt;&gt;();
      private OkHttpClient client;

      @Override
      public MethodStep url(String url) {
            this.url = url;
            return this;
      }

      @Override
      public BuildStep get() {
            this.method = Method.GET;
            return this;
      }

      @Override
      public BodyStep post() {
            this.method = Method.POST;
            return this;
      }

      @Override
      public BodyStep put() {
            this.method = Method.PUT;
            return this;
      }

      @Override
      public BuildStep delete() {
            this.method = Method.DELETE;
            return this;
      }

      @Override
      public BuildStep jsonBody(String json) {
            this.requestBody = RequestBody.create(
                json,
                MediaType.parse("application/json; charset=utf-8")
            );
            return this;
      }

      @Override
      public BuildStep formBody(Map&lt;String, String&gt; formData) {
            FormBody.Builder formBuilder = new FormBody.Builder();
            formData.forEach(formBuilder::add);
            this.requestBody = formBuilder.build();
            return this;
      }

      @Override
      public BuildStep emptyBody() {
            this.requestBody = RequestBody.create("", null);
            return this;
      }

      @Override
      public BuildStep header(String name, String value) {
            this.headers.put(name, value);
            return this;
      }

      @Override
      public BuildStep client(OkHttpClient client) {
            this.client = client;
            return this;
      }

      @Override
      public StepOkHttpRequest build() {
            return new StepOkHttpRequest(this);
      }
    }

    // ============ 静态工厂方法 ============

    public static UrlStep builder() {
      return new Builder();
    }

    // ============ 执行方法 ============

    public Response execute() throws IOException {
      return client.newCall(request).execute();
    }

    public void enqueue(Callback callback) {
      client.newCall(request).enqueue(callback);
    }
}
</pre></div>
<p><strong>使用示例:</strong></p>
<div class="jb51code"><pre class="brush:java;">public class OkHttpStepDemo {

    public static void main(String[] args) throws IOException {
      // GET请求
      StepOkHttpRequest getRequest = StepOkHttpRequest.builder()
                .url("https://jsonplaceholder.typicode.com/posts/1")
                .get()
                .header("Accept", "application/json")
                .build();

      try (Response response = getRequest.execute()) {
            System.out.println("GET Response: " + response.body().string());
      }

      // POST请求
      StepOkHttpRequest postRequest = StepOkHttpRequest.builder()
                .url("https://jsonplaceholder.typicode.com/posts")
                .post()
                .jsonBody("{\"title\":\"foo\",\"body\":\"bar\",\"userId\":1}")
                .header("Content-Type", "application/json")
                .build();

      try (Response response = postRequest.execute()) {
            System.out.println("POST Response: " + response.body().string());
      }
    }
}
</pre></div>
<p class="maodian"></p><h3>4.2 Spring RestTemplate增强</h3>
<div class="jb51code"><pre class="brush:java;">package com.example.spring;

import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;

/**
* Spring RestTemplate的Step Builder封装
*/
public class StepRestTemplate {

    private final RestTemplate restTemplate;
    private final String url;
    private final HttpMethod method;
    private final HttpHeaders headers;
    private final Object body;

    private StepRestTemplate(Builder builder) {
      this.restTemplate = builder.restTemplate != null ?
            builder.restTemplate : new RestTemplate();
      this.url = builder.url;
      this.method = builder.method;
      this.headers = builder.headers;
      this.body = builder.body;
    }

    // ============ Step接口定义 ============

    public interface UrlStep {
      MethodStep url(String url);
    }

    public interface MethodStep {
      BuildStep get();
      BodyStep post();
      BodyStep put();
      BuildStep delete();
    }

    public interface BodyStep {
      BuildStep body(Object body);
      BuildStep noBody();
    }

    public interface BuildStep {
      BuildStep header(String name, String value);
      BuildStep contentType(MediaType mediaType);
      BuildStep accept(MediaType... mediaTypes);
      BuildStep restTemplate(RestTemplate restTemplate);
      &lt;T&gt; T execute(Class&lt;T&gt; responseType);
      &lt;T&gt; ResponseEntity&lt;T&gt; executeForEntity(Class&lt;T&gt; responseType);
    }

    // ============ Builder实现 ============

    private static class Builder implements UrlStep, MethodStep, BodyStep, BuildStep {

      private RestTemplate restTemplate;
      private String url;
      private HttpMethod method;
      private HttpHeaders headers = new HttpHeaders();
      private Object body;

      @Override
      public MethodStep url(String url) {
            this.url = url;
            return this;
      }

      @Override
      public BuildStep get() {
            this.method = HttpMethod.GET;
            return this;
      }

      @Override
      public BodyStep post() {
            this.method = HttpMethod.POST;
            return this;
      }

      @Override
      public BodyStep put() {
            this.method = HttpMethod.PUT;
            return this;
      }

      @Override
      public BuildStep delete() {
            this.method = HttpMethod.DELETE;
            return this;
      }

      @Override
      public BuildStep body(Object body) {
            this.body = body;
            return this;
      }

      @Override
      public BuildStep noBody() {
            this.body = null;
            return this;
      }

      @Override
      public BuildStep header(String name, String value) {
            this.headers.add(name, value);
            return this;
      }

      @Override
      public BuildStep contentType(MediaType mediaType) {
            this.headers.setContentType(mediaType);
            return this;
      }

      @Override
      public BuildStep accept(MediaType... mediaTypes) {
            this.headers.setAccept(Arrays.asList(mediaTypes));
            return this;
      }

      @Override
      public BuildStep restTemplate(RestTemplate restTemplate) {
            this.restTemplate = restTemplate;
            return this;
      }

      @Override
      public &lt;T&gt; T execute(Class&lt;T&gt; responseType) {
            StepRestTemplate request = new StepRestTemplate(this);
            HttpEntity&lt;?&gt; entity = new HttpEntity&lt;&gt;(request.body, request.headers);
            ResponseEntity&lt;T&gt; response = request.restTemplate.exchange(
                request.url,
                request.method,
                entity,
                responseType
            );
            return response.getBody();
      }

      @Override
      public &lt;T&gt; ResponseEntity&lt;T&gt; executeForEntity(Class&lt;T&gt; responseType) {
            StepRestTemplate request = new StepRestTemplate(this);
            HttpEntity&lt;?&gt; entity = new HttpEntity&lt;&gt;(request.body, request.headers);
            return request.restTemplate.exchange(
                request.url,
                request.method,
                entity,
                responseType
            );
      }
    }

    // ============ 静态工厂方法 ============

    public static UrlStep builder() {
      return new Builder();
    }
}
</pre></div>
<p class="maodian"></p><h2>五、高级技巧与最佳实践</h2>
<p class="maodian"></p><h3>5.1 泛型Step Builder</h3>
<p>使用泛型可以创建更灵活的Step Builder:</p>
<div class="jb51code"><pre class="brush:java;">package com.example.generic;

/**
* 泛型SQL查询构建器
*/
public class SqlQuery&lt;T&gt; {

    private final String table;
    private final Class&lt;T&gt; resultType;
    private final String whereClause;
    private final String orderBy;
    private final Integer limit;

    private SqlQuery(Builder&lt;T&gt; builder) {
      this.table = builder.table;
      this.resultType = builder.resultType;
      this.whereClause = builder.whereClause;
      this.orderBy = builder.orderBy;
      this.limit = builder.limit;
    }

    // ============ Step接口定义 ============

    public interface TableStep&lt;T&gt; {
      ResultTypeStep&lt;T&gt; from(String table);
    }

    public interface ResultTypeStep&lt;T&gt; {
      BuildStep&lt;T&gt; resultType(Class&lt;T&gt; clazz);
    }

    public interface BuildStep&lt;T&gt; {
      BuildStep&lt;T&gt; where(String condition);
      BuildStep&lt;T&gt; orderBy(String column);
      BuildStep&lt;T&gt; limit(int limit);
      SqlQuery&lt;T&gt; build();
      List&lt;T&gt; execute();
    }

    // ============ Builder实现 ============

    private static class Builder&lt;T&gt; implements TableStep&lt;T&gt;, ResultTypeStep&lt;T&gt;, BuildStep&lt;T&gt; {

      private String table;
      private Class&lt;T&gt; resultType;
      private String whereClause;
      private String orderBy;
      private Integer limit;

      @Override
      public ResultTypeStep&lt;T&gt; from(String table) {
            this.table = table;
            return this;
      }

      @Override
      public BuildStep&lt;T&gt; resultType(Class&lt;T&gt; clazz) {
            this.resultType = clazz;
            return this;
      }

      @Override
      public BuildStep&lt;T&gt; where(String condition) {
            this.whereClause = condition;
            return this;
      }

      @Override
      public BuildStep&lt;T&gt; orderBy(String column) {
            this.orderBy = column;
            return this;
      }

      @Override
      public BuildStep&lt;T&gt; limit(int limit) {
            this.limit = limit;
            return this;
      }

      @Override
      public SqlQuery&lt;T&gt; build() {
            return new SqlQuery&lt;&gt;(this);
      }

      @Override
      public List&lt;T&gt; execute() {
            SqlQuery&lt;T&gt; query = build();
            return query.executeQuery();
      }
    }

    // ============ 静态工厂方法 ============

    public static &lt;T&gt; TableStep&lt;T&gt; select() {
      return new Builder&lt;T&gt;();
    }

    // ============ 执行方法 ============

    public List&lt;T&gt; executeQuery() {
      String sql = buildSql();
      System.out.println("执行SQL: " + sql);
      // 实际执行查询...
      return new ArrayList&lt;&gt;();
    }

    private String buildSql() {
      StringBuilder sql = new StringBuilder("SELECT * FROM ").append(table);
      if (whereClause != null) {
            sql.append(" WHERE ").append(whereClause);
      }
      if (orderBy != null) {
            sql.append(" ORDER BY ").append(orderBy);
      }
      if (limit != null) {
            sql.append(" LIMIT ").append(limit);
      }
      return sql.toString();
    }
}
</pre></div>
<p><strong>使用示例:</strong></p>
<div class="jb51code"><pre class="brush:java;">public class GenericBuilderDemo {

    public static class UserDto {
      private Long id;
      private String name;
      // getters and setters
    }

    public static void main(String[] args) {
      // 类型安全的查询
      List&lt;UserDto&gt; users = SqlQuery.&lt;UserDto&gt;select()
                .from("users")
                .resultType(UserDto.class)
                .where("age &gt; 18")
                .orderBy("created_at DESC")
                .limit(10)
                .execute();

      System.out.println("查询结果: " + users);
    }
}
</pre></div>
<p class="maodian"></p><h3>5.2 条件分支的Step Builder</h3>
<p>有时需要根据条件选择不同的构建路径:</p>
<div class="jb51code"><pre class="brush:java;">package com.example.conditional;

/**
* 支付请求构建器 - 支持多种支付方式
*/
public class PaymentRequest {

    private final String orderId;
    private final PaymentMethod method;
    private final double amount;

    // 支付宝特有字段
    private final String alipayAccount;

    // 微信特有字段
    private final String wechatOpenId;

    // 银行卡特有字段
    private final String cardNumber;
    private final String cardHolder;

    public enum PaymentMethod {
      ALIPAY, WECHAT, BANK_CARD
    }

    private PaymentRequest(BuilderBase builder) {
      this.orderId = builder.orderId;
      this.method = builder.method;
      this.amount = builder.amount;
      this.alipayAccount = builder instanceof AlipayBuilder ?
            ((AlipayBuilder) builder).alipayAccount : null;
      this.wechatOpenId = builder instanceof WechatBuilder ?
            ((WechatBuilder) builder).wechatOpenId : null;
      this.cardNumber = builder instanceof BankCardBuilder ?
            ((BankCardBuilder) builder).cardNumber : null;
      this.cardHolder = builder instanceof BankCardBuilder ?
            ((BankCardBuilder) builder).cardHolder : null;
    }

    // ============ Step接口定义 ============

    public interface OrderStep {
      AmountStep orderId(String orderId);
    }

    public interface AmountStep {
      MethodStep amount(double amount);
    }

    public interface MethodStep {
      AlipayStep alipay();
      WechatStep wechat();
      BankCardStep bankCard();
    }

    public interface AlipayStep {
      BuildStep account(String alipayAccount);
    }

    public interface WechatStep {
      BuildStep openId(String wechatOpenId);
    }

    public interface BankCardStep {
      CardHolderStep cardNumber(String cardNumber);
    }

    public interface CardHolderStep {
      BuildStep cardHolder(String cardHolder);
    }

    public interface BuildStep {
      PaymentRequest build();
    }

    // ============ Builder基类 ============

    private static abstract class BuilderBase implements OrderStep, AmountStep, MethodStep {
      protected String orderId;
      protected double amount;
      protected PaymentMethod method;

      @Override
      public AmountStep orderId(String orderId) {
            this.orderId = orderId;
            return this;
      }

      @Override
      public MethodStep amount(double amount) {
            this.amount = amount;
            return this;
      }
    }

    // ============ 具体Builder实现 ============

    private static class AlipayBuilder extends BuilderBase implements AlipayStep, BuildStep {
      private String alipayAccount;

      @Override
      public AlipayStep alipay() {
            this.method = PaymentMethod.ALIPAY;
            return this;
      }

      @Override
      public WechatStep wechat() {
            throw new UnsupportedOperationException();
      }

      @Override
      public BankCardStep bankCard() {
            throw new UnsupportedOperationException();
      }

      @Override
      public BuildStep account(String alipayAccount) {
            this.alipayAccount = alipayAccount;
            return this;
      }

      @Override
      public PaymentRequest build() {
            return new PaymentRequest(this);
      }
    }

    private static class WechatBuilder extends BuilderBase implements WechatStep, BuildStep {
      private String wechatOpenId;

      @Override
      public AlipayStep alipay() {
            throw new UnsupportedOperationException();
      }

      @Override
      public WechatStep wechat() {
            this.method = PaymentMethod.WECHAT;
            return this;
      }

      @Override
      public BankCardStep bankCard() {
            throw new UnsupportedOperationException();
      }

      @Override
      public BuildStep openId(String wechatOpenId) {
            this.wechatOpenId = wechatOpenId;
            return this;
      }

      @Override
      public PaymentRequest build() {
            return new PaymentRequest(this);
      }
    }

    private static class BankCardBuilder extends BuilderBase
            implements BankCardStep, CardHolderStep, BuildStep {
      private String cardNumber;
      private String cardHolder;

      @Override
      public AlipayStep alipay() {
            throw new UnsupportedOperationException();
      }

      @Override
      public WechatStep wechat() {
            throw new UnsupportedOperationException();
      }

      @Override
      public BankCardStep bankCard() {
            this.method = PaymentMethod.BANK_CARD;
            return this;
      }

      @Override
      public CardHolderStep cardNumber(String cardNumber) {
            this.cardNumber = cardNumber;
            return this;
      }

      @Override
      public BuildStep cardHolder(String cardHolder) {
            this.cardHolder = cardHolder;
            return this;
      }

      @Override
      public PaymentRequest build() {
            return new PaymentRequest(this);
      }
    }

    // ============ 统一入口 ============

    public static OrderStep builder() {
      return new UnifiedBuilder();
    }

    private static class UnifiedBuilder extends BuilderBase {
      @Override
      public AlipayStep alipay() {
            AlipayBuilder builder = new AlipayBuilder();
            builder.orderId = this.orderId;
            builder.amount = this.amount;
            return builder.alipay();
      }

      @Override
      public WechatStep wechat() {
            WechatBuilder builder = new WechatBuilder();
            builder.orderId = this.orderId;
            builder.amount = this.amount;
            return builder.wechat();
      }

      @Override
      public BankCardStep bankCard() {
            BankCardBuilder builder = new BankCardBuilder();
            builder.orderId = this.orderId;
            builder.amount = this.amount;
            return builder.bankCard();
      }
    }

    @Override
    public String toString() {
      return "PaymentRequest{" +
                "orderId='" + orderId + '\'' +
                ", method=" + method +
                ", amount=" + amount +
                ", alipayAccount='" + alipayAccount + '\'' +
                ", wechatOpenId='" + wechatOpenId + '\'' +
                ", cardNumber='" + cardNumber + '\'' +
                ", cardHolder='" + cardHolder + '\'' +
                '}';
    }
}
</pre></div>
<p><strong>使用示例:</strong></p>
<div class="jb51code"><pre class="brush:java;">public class PaymentDemo {

    public static void main(String[] args) {
      // 支付宝支付
      PaymentRequest alipayPayment = PaymentRequest.builder()
                .orderId("ORDER_001")
                .amount(99.99)
                .alipay()
                .account("user@alipay.com")
                .build();

      System.out.println(alipayPayment);

      // 微信支付
      PaymentRequest wechatPayment = PaymentRequest.builder()
                .orderId("ORDER_002")
                .amount(199.99)
                .wechat()
                .openId("wx_openid_123456")
                .build();

      System.out.println(wechatPayment);

      // 银行卡支付
      PaymentRequest bankPayment = PaymentRequest.builder()
                .orderId("ORDER_003")
                .amount(299.99)
                .bankCard()
                .cardNumber("6222021234567890")
                .cardHolder("Zhang San")
                .build();

      System.out.println(bankPayment);
    }
}
</pre></div>
<p class="maodian"></p><h3>5.3 验证增强</h3>
<p>在build()方法中添加复杂验证逻辑:</p>
<div class="jb51code"><pre class="brush:java;">public class ValidatedUser {

    private final String username;
    private final String password;
    private final String email;
    private final int age;

    private ValidatedUser(Builder builder) {
      this.username = builder.username;
      this.password = builder.password;
      this.email = builder.email;
      this.age = builder.age;
    }

    // ... Step接口定义 ...

    private static class Builder implements UsernameStep, PasswordStep, EmailStep, AgeStep, BuildStep {

      private String username;
      private String password;
      private String email;
      private int age;

      // ... 各步骤实现 ...

      @Override
      public ValidatedUser build() {
            // 用户名验证
            if (username.length() &lt; 3 || username.length() &gt; 20) {
                throw new IllegalArgumentException("用户名长度必须在3-20之间");
            }
            if (!username.matches("^+$")) {
                throw new IllegalArgumentException("用户名只能包含字母、数字和下划线");
            }

            // 密码验证
            if (password.length() &lt; 8) {
                throw new IllegalArgumentException("密码长度不能少于8位");
            }
            if (!password.matches(".*.*")) {
                throw new IllegalArgumentException("密码必须包含至少一个大写字母");
            }
            if (!password.matches(".*.*")) {
                throw new IllegalArgumentException("密码必须包含至少一个数字");
            }

            // 邮箱验证
            if (!email.matches("^+@+$")) {
                throw new IllegalArgumentException("邮箱格式不正确");
            }

            // 年龄验证
            if (age &lt; 18 || age &gt; 120) {
                throw new IllegalArgumentException("年龄必须在18-120之间");
            }

            return new ValidatedUser(this);
      }
    }

    public static UsernameStep builder() {
      return new Builder();
    }
}
</pre></div>
<p class="maodian"></p><h2>六、Step Builder vs 其他模式</h2>
<p class="maodian"></p><h3>6.1 对比表格</h3>
<div class="jb51code"><pre class="brush:java;">特性对比:
┌────────────────┬──────────────┬──────────────┬──────────────┐
│    特性      │ Step Builder │ 传统Builder│ 构造函数   │
├────────────────┼──────────────┼──────────────┼──────────────┤
│ 必填参数检查   │ 编译期       │ 运行期       │ 编译期       │
├────────────────┼──────────────┼──────────────┼──────────────┤
│ 可读性         │ ★★★★★       │ ★★★★☆       │ ★★☆☆☆       │
├────────────────┼──────────────┼──────────────┼──────────────┤
│ 类型安全       │ ★★★★★       │ ★★★☆☆       │ ★★★★★       │
├────────────────┼──────────────┼──────────────┼──────────────┤
│ 实现复杂度   │ ★★★★☆       │ ★★☆☆☆       │ ★☆☆☆☆       │
├────────────────┼──────────────┼──────────────┼──────────────┤
│ 扩展性         │ ★★★★★       │ ★★★★☆       │ ★★☆☆☆       │
├────────────────┼──────────────┼──────────────┼──────────────┤
│ IDE支持      │ ★★★★★       │ ★★★★☆       │ ★★★☆☆       │
└────────────────┴──────────────┴──────────────┴──────────────┘
</pre></div>
<p class="maodian"></p><h3>6.2 选择指南</h3>
<p><strong>使用Step Builder的场景:</strong></p>
<ul><li>✅ 对象有多个必填参数</li><li>✅ 需要编译期保证参数完整性</li><li>✅ 构建过程有明确的步骤顺序</li><li>✅ API需要高度的类型安全</li></ul>
<p><strong>使用传统Builder的场景:</strong></p>
<ul><li>✅ 大部分参数都是可选的</li><li>✅ 参数没有明确的顺序要求</li><li>✅ 需要简单实现</li></ul>
<p><strong>使用构造函数的场景:</strong></p>
<ul><li>✅ 参数很少(1-3个)</li><li>✅ 所有参数都是必填的</li><li>✅ 对象创建非常简单</li></ul>
<p class="maodian"></p><h2>七、实际生产经验</h2>
<p class="maodian"></p><h3>7.1 Lombok集成</h3>
<p>可以使用Lombok减少样板代码:</p>
<div class="jb51code"><pre class="brush:java;">import lombok.Builder;
import lombok.Value;

// 注意:Lombok的@Builder不支持Step Builder
// 需要手动实现Step接口

@Value
public class Product {
    String id;
    String name;
    double price;
    String category;

    // 手动实现Step Builder
    public static IdStep builder() {
      return new StepBuilder();
    }

    // Step接口定义...

    private static class StepBuilder implements IdStep, NameStep, PriceStep, CategoryStep, BuildStep {
      private String id;
      private String name;
      private double price;
      private String category;

      // 实现各步骤方法...

      @Override
      public Product build() {
            return new Product(id, name, price, category);
      }
    }
}
</pre></div>
<p class="maodian"></p><h3>7.2 测试友好性</h3>
<p>Step Builder模式使测试数据构建更加清晰:</p>
<div class="jb51code"><pre class="brush:java;">public class UserTest {

    @Test
    public void testUserCreation() {
      // 测试数据构建清晰明了
      User validUser = User.builder()
                .username("testuser")
                .password("TestPass123")
                .email("test@example.com")
                .age(25)
                .build();

      assertNotNull(validUser);
      assertEquals("testuser", validUser.getUsername());
    }

    @Test
    public void testInvalidEmail() {
      // 编译器强制设置所有必填字段
      assertThrows(IllegalArgumentException.class, () -&gt; {
            User.builder()
                  .username("testuser")
                  .password("TestPass123")
                  .email("invalid-email")// 无效邮箱
                  .age(25)
                  .build();
      });
    }
}
</pre></div>
<p class="maodian"></p><h3>7.3 性能考虑</h3>
<p>Step Builder的性能开销主要来自:</p>
<ul><li>多个接口的实现</li><li>对象创建时的类型转换</li></ul>
<p><strong>优化建议:</strong></p>
<div class="jb51code"><pre class="brush:java;">// 1. 使用final字段减少内存占用
private static class Builder implements ... {
    private final StringBuilder urlBuilder = new StringBuilder();
    // ...
}

// 2. 对于高频调用,考虑对象池
public class ObjectPooledBuilder {
    private static final ThreadLocal&lt;Builder&gt; POOL =
      ThreadLocal.withInitial(Builder::new);

    public static BuilderStep builder() {
      Builder builder = POOL.get();
      builder.reset();
      return builder;
    }
}

// 3. 延迟验证到build()方法
@Override
public User build() {
    validateAll();// 只在最后验证一次
    return new User(this);
}
</pre></div>
<p class="maodian"></p><h2>八、常见问题与解决方案</h2>
<p class="maodian"></p><h3>8.1 如何处理可选参数组</h3>
<div class="jb51code"><pre class="brush:java;">public interface BuildStep {
    // 方案1: 单独的可选参数方法
    BuildStep optionalField1(String value);
    BuildStep optionalField2(String value);

    // 方案2: 配置对象
    BuildStep withOptions(Options options);

    User build();
}

public class Options {
    private String field1;
    private String field2;

    public static Options create() {
      return new Options();
    }

    public Options field1(String value) {
      this.field1 = value;
      return this;
    }

    public Options field2(String value) {
      this.field2 = value;
      return this;
    }
}
</pre></div>
<p class="maodian"></p><h3>8.2 如何支持不可变对象</h3>
<div class="jb51code"><pre class="brush:java;">@Value// Lombok注解,生成不可变对象
public class ImmutableUser {
    String username;
    String password;
    String email;

    // Step Builder确保所有必填字段都被设置
    // build()返回不可变对象
}
</pre></div>
<p class="maodian"></p><h3>8.3 如何处理继承</h3>
<div class="jb51code"><pre class="brush:java;">public class Employee extends Person {

    private final String employeeId;
    private final String department;

    // 继承父类的Step Builder
    public static EmployeeIdStep builder() {
      return new Builder();
    }

    // 扩展父类的Step接口
    public interface EmployeeIdStep extends Person.NameStep {
      DepartmentStep employeeId(String id);
    }

    public interface DepartmentStep {
      Person.BuildStep department(String dept);
    }

    private static class Builder extends Person.Builder
            implements EmployeeIdStep, DepartmentStep {

      private String employeeId;
      private String department;

      @Override
      public DepartmentStep employeeId(String id) {
            this.employeeId = id;
            return this;
      }

      @Override
      public Person.BuildStep department(String dept) {
            this.department = dept;
            return this;
      }

      @Override
      public Employee build() {
            return new Employee(this);
      }
    }
}
</pre></div>
<p class="maodian"></p><h2>九、总结</h2>
<p class="maodian"></p><h3>9.1 核心优势</h3>
<ol><li><strong>编译期安全</strong>:在编译时就能发现缺少必填参数的错误</li><li><strong>清晰的API</strong>:IDE自动提示引导开发者完成所有步骤</li><li><strong>类型安全</strong>:利用类型系统保证调用顺序</li><li><strong>自文档化</strong>:代码本身就说明了构建流程</li></ol>
<p class="maodian"></p><h3>9.2 适用场景总结</h3>
<div class="jb51code"><pre class="brush:java;">推荐使用Step Builder的情况:
├─ 对象有3个以上必填参数
├─ 需要严格的参数验证
├─ 构建过程有明确的步骤顺序
├─ 团队希望提高代码质量
└─ 公共API需要防止误用

不推荐使用的情况:
├─ 简单对象(参数少于3个)
├─ 参数都是可选的
├─ 快速原型开发
└─ 性能极度敏感的场景
</pre></div>
<p class="maodian"></p><h3>9.3 最佳实践清单</h3>
<ul><li>✅ 为每个必填参数创建独立的Step接口</li><li>✅ 将可选参数放在最后的BuildStep中</li><li>✅ 在build()方法中进行最终验证</li><li>✅ 使用有意义的接口命名(如UsernameStep)</li><li>✅ 提供清晰的JavaDoc文档</li><li>✅ 考虑使用代码生成工具减少重复代码</li><li>❌ 不要在Step方法中进行复杂验证</li><li>❌ 不要过度使用(简单对象用普通Builder)</li></ul>
<p class="maodian"></p><h2>总结&nbsp;</h2>
<p>到此这篇关于Java开发中StepBuilder模式详解的文章就介绍到这了,更多相关Java&nbsp;StepBuilder模式详解内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>JAVA实现单例模式的四种方法和一些特点</li><li>Java中的观察者模式实例讲解</li><li>Java中Builder模式的实现详解</li><li>Java单例模式的6种实现方式详解</li><li>Java设计模式之策略模式示例详解</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: Java开发中StepBuilder模式详解