最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java開發(fā)中StepBuilder模式詳解

 更新時間:2026年01月12日 08:27:58   作者:雨中飄蕩的記憶  
Step builder多階段步驟構(gòu)造器模式是一種對象創(chuàng)建軟件設(shè)計模式,與傳統(tǒng)構(gòu)建器模式進行比較時,步驟構(gòu)建器模式提供了一些簡潔的好處,這篇文章主要介紹了Java開發(fā)中StepBuilder模式的相關(guān)資料,需要的朋友可以參考下

一、什么是Step Builder模式

1.1 傳統(tǒng)Builder模式的局限性

在Java開發(fā)中,我們經(jīng)常使用Builder模式來構(gòu)建復(fù)雜對象。傳統(tǒng)的Builder模式雖然解決了構(gòu)造函數(shù)參數(shù)過多的問題,但存在一個明顯的缺陷:無法在編譯期保證必填參數(shù)的完整性。

傳統(tǒng)Builder的問題示例:

// 傳統(tǒng)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);
        }
    }
}

// 使用時可能會忘記設(shè)置必填字段
User user = new User.Builder()
    .username("john")
    // 忘記設(shè)置password和email
    .phone("123456")
    .build();  // 運行時才會拋出異常!

1.2 Step Builder模式的優(yōu)勢

Step Builder模式(也稱為Staged Builder或Telescopic Builder)通過類型系統(tǒng)在編譯期強制要求按順序設(shè)置必填參數(shù),從而避免了運行時錯誤。

核心思想:

  • 每個必填參數(shù)對應(yīng)一個構(gòu)建步驟(Step)
  • 每個步驟只暴露下一步需要的方法
  • 利用接口和泛型確保類型安全
  • 編譯器強制完成所有必填步驟

Step Builder的調(diào)用流程:

Step 1: Username    Step 2: Password    Step 3: Email    Step 4: Build
   ↓                    ↓                   ↓                ↓
[username()] ──→ [password()] ──→ [email()] ──→ [build()]
                                               [phone()]
                                               [age()]

二、Step Builder基礎(chǔ)實現(xiàn)

2.1 簡單示例:用戶注冊

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: 設(shè)置用戶名
     */
    public interface UsernameStep {
        PasswordStep username(String username);
    }

    /**
     * 步驟2: 設(shè)置密碼
     */
    public interface PasswordStep {
        EmailStep password(String password);
    }

    /**
     * 步驟3: 設(shè)置郵箱
     */
    public interface EmailStep {
        BuildStep email(String email);
    }

    /**
     * 步驟4: 構(gòu)建對象(可選參數(shù))
     */
    public interface BuildStep {
        BuildStep phone(String phone);
        BuildStep age(Integer age);
        User build();
    }

    // ============ Builder實現(xiàn)類 ============

    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);
        }
    }

    // ============ 靜態(tài)工廠方法 ============

    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 +
                '}';
    }
}

使用示例:

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);

        // ? 只設(shè)置必填字段
        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();  // 編譯失?。赫也坏絙uild()方法
    }
}

2.2 工作原理分析

類型系統(tǒng)保證調(diào)用順序:

User.builder()                     返回類型: UsernameStep
    ↓ 只能調(diào)用username()
.username("john")                  返回類型: PasswordStep
    ↓ 只能調(diào)用password()
.password("pass123")               返回類型: EmailStep
    ↓ 只能調(diào)用email()
.email("john@example.com")         返回類型: BuildStep
    ↓ 可以調(diào)用phone()、age()或build()
.phone("123456")                   返回類型: BuildStep
    ↓ 可以調(diào)用age()或build()
.build()                           返回類型: User

類型安全的關(guān)鍵:

  1. 接口鏈:每個步驟返回不同的接口類型
  2. 單一實現(xiàn):Builder類實現(xiàn)所有接口
  3. 方法可見性:每個接口只暴露特定方法
  4. 編譯期檢查:IDE和編譯器強制按順序調(diào)用

三、實戰(zhàn)案例:HTTP請求構(gòu)建器

3.1 場景分析

在構(gòu)建HTTP客戶端時,某些參數(shù)是必需的(如URL、HTTP方法),而某些是可選的(如請求頭、超時時間)。使用Step Builder可以確保必填參數(shù)不會遺漏。

3.2 完整實現(xiàn)

package com.example.http;

import java.util.*;

/**
 * HTTP請求構(gòu)建器 - Step Builder模式
 */
public class HttpRequest {

    private final String url;
    private final HttpMethod method;
    private final Map<String, String> 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<>(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<String, String> headers);
        BuildStep body(String body);
        BuildStep timeout(int seconds);
        BuildStep followRedirects(boolean follow);
        HttpRequest build();
    }

    // ============ Builder實現(xiàn) ============

    private static class Builder implements UrlStep, MethodStep, BuildStep {

        private String url;
        private HttpMethod method;
        private Map<String, String> headers = new HashMap<>();
        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<String, String> 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 <= 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);
        }
    }

    // ============ 靜態(tài)工廠方法 ============

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

    // ============ 執(zhí)行方法 ============

    public void execute() {
        System.out.println("執(zhí)行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<String, String> getHeaders() { return headers; }
    public String getBody() { return body; }
    public int getTimeoutSeconds() { return timeoutSeconds; }
    public boolean isFollowRedirects() { return followRedirects; }
}

使用示例:

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();
    }
}

四、開源框架中的Step Builder應(yīng)用

4.1 OkHttp Request Builder分析

雖然OkHttp的Request.Builder不是嚴格的Step Builder,但我們可以用Step Builder改進它:

package com.example.okhttp;

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

/**
 * 改進的OkHttp請求構(gòu)建器
 */
public class StepOkHttpRequest {

    private final Request request;
    private final OkHttpClient client;

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

        // 設(shè)置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<String, String> formData);
        BuildStep emptyBody();
    }

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

    // ============ Builder實現(xiàn) ============

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

        private String url;
        private Method method;
        private RequestBody requestBody;
        private Map<String, String> headers = new HashMap<>();
        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<String, String> 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);
        }
    }

    // ============ 靜態(tài)工廠方法 ============

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

    // ============ 執(zhí)行方法 ============

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

    public void enqueue(Callback callback) {
        client.newCall(request).enqueue(callback);
    }
}

使用示例:

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());
        }
    }
}

4.2 Spring RestTemplate增強

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);
        <T> T execute(Class<T> responseType);
        <T> ResponseEntity<T> executeForEntity(Class<T> responseType);
    }

    // ============ Builder實現(xiàn) ============

    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 <T> T execute(Class<T> responseType) {
            StepRestTemplate request = new StepRestTemplate(this);
            HttpEntity<?> entity = new HttpEntity<>(request.body, request.headers);
            ResponseEntity<T> response = request.restTemplate.exchange(
                request.url,
                request.method,
                entity,
                responseType
            );
            return response.getBody();
        }

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

    // ============ 靜態(tài)工廠方法 ============

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

五、高級技巧與最佳實踐

5.1 泛型Step Builder

使用泛型可以創(chuàng)建更靈活的Step Builder:

package com.example.generic;

/**
 * 泛型SQL查詢構(gòu)建器
 */
public class SqlQuery<T> {

    private final String table;
    private final Class<T> resultType;
    private final String whereClause;
    private final String orderBy;
    private final Integer limit;

    private SqlQuery(Builder<T> 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<T> {
        ResultTypeStep<T> from(String table);
    }

    public interface ResultTypeStep<T> {
        BuildStep<T> resultType(Class<T> clazz);
    }

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

    // ============ Builder實現(xiàn) ============

    private static class Builder<T> implements TableStep<T>, ResultTypeStep<T>, BuildStep<T> {

        private String table;
        private Class<T> resultType;
        private String whereClause;
        private String orderBy;
        private Integer limit;

        @Override
        public ResultTypeStep<T> from(String table) {
            this.table = table;
            return this;
        }

        @Override
        public BuildStep<T> resultType(Class<T> clazz) {
            this.resultType = clazz;
            return this;
        }

        @Override
        public BuildStep<T> where(String condition) {
            this.whereClause = condition;
            return this;
        }

        @Override
        public BuildStep<T> orderBy(String column) {
            this.orderBy = column;
            return this;
        }

        @Override
        public BuildStep<T> limit(int limit) {
            this.limit = limit;
            return this;
        }

        @Override
        public SqlQuery<T> build() {
            return new SqlQuery<>(this);
        }

        @Override
        public List<T> execute() {
            SqlQuery<T> query = build();
            return query.executeQuery();
        }
    }

    // ============ 靜態(tài)工廠方法 ============

    public static <T> TableStep<T> select() {
        return new Builder<T>();
    }

    // ============ 執(zhí)行方法 ============

    public List<T> executeQuery() {
        String sql = buildSql();
        System.out.println("執(zhí)行SQL: " + sql);
        // 實際執(zhí)行查詢...
        return new ArrayList<>();
    }

    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();
    }
}

使用示例:

public class GenericBuilderDemo {

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

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

        System.out.println("查詢結(jié)果: " + users);
    }
}

5.2 條件分支的Step Builder

有時需要根據(jù)條件選擇不同的構(gòu)建路徑:

package com.example.conditional;

/**
 * 支付請求構(gòu)建器 - 支持多種支付方式
 */
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實現(xiàn) ============

    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);
        }
    }

    // ============ 統(tǒng)一入口 ============

    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 + '\'' +
                '}';
    }
}

使用示例:

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);
    }
}

5.3 驗證增強

在build()方法中添加復(fù)雜驗證邏輯:

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;

        // ... 各步驟實現(xiàn) ...

        @Override
        public ValidatedUser build() {
            // 用戶名驗證
            if (username.length() < 3 || username.length() > 20) {
                throw new IllegalArgumentException("用戶名長度必須在3-20之間");
            }
            if (!username.matches("^[a-zA-Z0-9_]+$")) {
                throw new IllegalArgumentException("用戶名只能包含字母、數(shù)字和下劃線");
            }

            // 密碼驗證
            if (password.length() < 8) {
                throw new IllegalArgumentException("密碼長度不能少于8位");
            }
            if (!password.matches(".*[A-Z].*")) {
                throw new IllegalArgumentException("密碼必須包含至少一個大寫字母");
            }
            if (!password.matches(".*[0-9].*")) {
                throw new IllegalArgumentException("密碼必須包含至少一個數(shù)字");
            }

            // 郵箱驗證
            if (!email.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$")) {
                throw new IllegalArgumentException("郵箱格式不正確");
            }

            // 年齡驗證
            if (age < 18 || age > 120) {
                throw new IllegalArgumentException("年齡必須在18-120之間");
            }

            return new ValidatedUser(this);
        }
    }

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

六、Step Builder vs 其他模式

6.1 對比表格

特性對比:
┌────────────────┬──────────────┬──────────────┬──────────────┐
│    特性        │ Step Builder │ 傳統(tǒng)Builder  │ 構(gòu)造函數(shù)     │
├────────────────┼──────────────┼──────────────┼──────────────┤
│ 必填參數(shù)檢查   │ 編譯期       │ 運行期       │ 編譯期       │
├────────────────┼──────────────┼──────────────┼──────────────┤
│ 可讀性         │ ★★★★★       │ ★★★★☆       │ ★★☆☆☆       │
├────────────────┼──────────────┼──────────────┼──────────────┤
│ 類型安全       │ ★★★★★       │ ★★★☆☆       │ ★★★★★       │
├────────────────┼──────────────┼──────────────┼──────────────┤
│ 實現(xiàn)復(fù)雜度     │ ★★★★☆       │ ★★☆☆☆       │ ★☆☆☆☆       │
├────────────────┼──────────────┼──────────────┼──────────────┤
│ 擴展性         │ ★★★★★       │ ★★★★☆       │ ★★☆☆☆       │
├────────────────┼──────────────┼──────────────┼──────────────┤
│ IDE支持        │ ★★★★★       │ ★★★★☆       │ ★★★☆☆       │
└────────────────┴──────────────┴──────────────┴──────────────┘

6.2 選擇指南

使用Step Builder的場景:

  • ? 對象有多個必填參數(shù)
  • ? 需要編譯期保證參數(shù)完整性
  • ? 構(gòu)建過程有明確的步驟順序
  • ? API需要高度的類型安全

使用傳統(tǒng)Builder的場景:

  • ? 大部分參數(shù)都是可選的
  • ? 參數(shù)沒有明確的順序要求
  • ? 需要簡單實現(xiàn)

使用構(gòu)造函數(shù)的場景:

  • ? 參數(shù)很少(1-3個)
  • ? 所有參數(shù)都是必填的
  • ? 對象創(chuàng)建非常簡單

七、實際生產(chǎn)經(jīng)驗

7.1 Lombok集成

可以使用Lombok減少樣板代碼:

import lombok.Builder;
import lombok.Value;

// 注意:Lombok的@Builder不支持Step Builder
// 需要手動實現(xiàn)Step接口

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

    // 手動實現(xiàn)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;

        // 實現(xiàn)各步驟方法...

        @Override
        public Product build() {
            return new Product(id, name, price, category);
        }
    }
}

7.2 測試友好性

Step Builder模式使測試數(shù)據(jù)構(gòu)建更加清晰:

public class UserTest {

    @Test
    public void testUserCreation() {
        // 測試數(shù)據(jù)構(gòu)建清晰明了
        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() {
        // 編譯器強制設(shè)置所有必填字段
        assertThrows(IllegalArgumentException.class, () -> {
            User.builder()
                    .username("testuser")
                    .password("TestPass123")
                    .email("invalid-email")  // 無效郵箱
                    .age(25)
                    .build();
        });
    }
}

7.3 性能考慮

Step Builder的性能開銷主要來自:

  • 多個接口的實現(xiàn)
  • 對象創(chuàng)建時的類型轉(zhuǎn)換

優(yōu)化建議:

// 1. 使用final字段減少內(nèi)存占用
private static class Builder implements ... {
    private final StringBuilder urlBuilder = new StringBuilder();
    // ...
}

// 2. 對于高頻調(diào)用,考慮對象池
public class ObjectPooledBuilder {
    private static final ThreadLocal<Builder> 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);
}

八、常見問題與解決方案

8.1 如何處理可選參數(shù)組

public interface BuildStep {
    // 方案1: 單獨的可選參數(shù)方法
    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;
    }
}

8.2 如何支持不可變對象

@Value  // Lombok注解,生成不可變對象
public class ImmutableUser {
    String username;
    String password;
    String email;

    // Step Builder確保所有必填字段都被設(shè)置
    // build()返回不可變對象
}

8.3 如何處理繼承

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);
        }
    }
}

九、總結(jié)

9.1 核心優(yōu)勢

  1. 編譯期安全:在編譯時就能發(fā)現(xiàn)缺少必填參數(shù)的錯誤
  2. 清晰的API:IDE自動提示引導(dǎo)開發(fā)者完成所有步驟
  3. 類型安全:利用類型系統(tǒng)保證調(diào)用順序
  4. 自文檔化:代碼本身就說明了構(gòu)建流程

9.2 適用場景總結(jié)

推薦使用Step Builder的情況:
├─ 對象有3個以上必填參數(shù)
├─ 需要嚴格的參數(shù)驗證
├─ 構(gòu)建過程有明確的步驟順序
├─ 團隊希望提高代碼質(zhì)量
└─ 公共API需要防止誤用

不推薦使用的情況:
├─ 簡單對象(參數(shù)少于3個)
├─ 參數(shù)都是可選的
├─ 快速原型開發(fā)
└─ 性能極度敏感的場景

9.3 最佳實踐清單

  • ? 為每個必填參數(shù)創(chuàng)建獨立的Step接口
  • ? 將可選參數(shù)放在最后的BuildStep中
  • ? 在build()方法中進行最終驗證
  • ? 使用有意義的接口命名(如UsernameStep)
  • ? 提供清晰的JavaDoc文檔
  • ? 考慮使用代碼生成工具減少重復(fù)代碼
  • ? 不要在Step方法中進行復(fù)雜驗證
  • ? 不要過度使用(簡單對象用普通Builder)

總結(jié) 

到此這篇關(guān)于Java開發(fā)中StepBuilder模式詳解的文章就介紹到這了,更多相關(guān)Java StepBuilder模式詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java給實體每一個字段賦默認值詳細代碼示例

    Java給實體每一個字段賦默認值詳細代碼示例

    這篇文章主要給大家介紹了關(guān)于Java給實體每一個字段賦默認值的相關(guān)資料,在編程過程中有時會出現(xiàn)這樣一種情況,在查詢無結(jié)果時我們需要給實體賦默認值,需要的朋友可以參考下
    2023-09-09
  • mybaits中if條件中怎樣判斷布爾值

    mybaits中if條件中怎樣判斷布爾值

    這篇文章主要介紹了mybaits中if條件中怎樣判斷布爾值問題,具有很好的參考價值,希望對大家有所幫助,
    2023-08-08
  • java虛擬線程的超詳細講解

    java虛擬線程的超詳細講解

    虛擬線程是由Java運行時而不是操作系統(tǒng)實現(xiàn)的Java線程,和傳統(tǒng)線程(或稱之為平臺線程)之間的主要區(qū)別在于,我們可以很容易地在同一個Java進程中運行大量活動的虛擬線程,甚至數(shù)百萬個,這篇文章主要介紹了java虛擬線程的相關(guān)資料,需要的朋友可以參考下
    2025-10-10
  • 解決Maven的pom.xml中設(shè)置repository不起作用問題

    解決Maven的pom.xml中設(shè)置repository不起作用問題

    這篇文章主要介紹了解決Maven的pom.xml中設(shè)置repository不起作用問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • springmvc接收json串,轉(zhuǎn)換為實體類List方法

    springmvc接收json串,轉(zhuǎn)換為實體類List方法

    今天小編就為大家分享一篇springmvc接收json串,轉(zhuǎn)換為實體類List方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-08-08
  • Java樹形菜單的創(chuàng)建

    Java樹形菜單的創(chuàng)建

    這篇文章主要為大家詳細介紹了Java圖形用戶界面中樹形菜單的創(chuàng)建樹形菜單的創(chuàng)建,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2015-10-10
  • java常見的五種加密算法使用方法舉例

    java常見的五種加密算法使用方法舉例

    這篇文章主要介紹了java常見的加密算法使用的相關(guān)資料,分別是BCrypt、MD5、RSA、AES和SM4這五種加密算法,并簡要描述了它們的特點和應(yīng)用場景,給出了詳細的代碼示例,需要的朋友可以參考下
    2025-03-03
  • Java代理的幾種實現(xiàn)方式總結(jié)

    Java代理的幾種實現(xiàn)方式總結(jié)

    本文將通過例子說明java代理的幾種實現(xiàn)方式,并比較它們之間的差異,文中通過代碼示例給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作有一定的參考價值,需要的朋友可以參考下
    2023-12-12
  • SpringBoot的Security和OAuth2的使用示例小結(jié)

    SpringBoot的Security和OAuth2的使用示例小結(jié)

    這篇文章主要介紹了SpringBoot的Security和OAuth2的使用,本文通過示例圖文相結(jié)合給大家講解的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • Java 邏輯運算符中&&與&,||與|的區(qū)別

    Java 邏輯運算符中&&與&,||與|的區(qū)別

    這篇文章主要介紹了Java中&&與&,||與|的區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2017-05-05

最新評論

昭觉县| 平原县| 北辰区| 三门峡市| 正阳县| 新化县| 台北市| 奉化市| 都匀市| 家居| 洪雅县| 酉阳| 黔西县| 花莲县| 区。| 霍林郭勒市| 华容县| 丹巴县| 临城县| 昂仁县| 桐梓县| 平原县| 嘉定区| 本溪| 察雅县| 慈利县| 霸州市| 盐源县| 建瓯市| 塔河县| 南充市| 明溪县| 临武县| 辛集市| 喀什市| 电白县| 太谷县| 岚皋县| 湘阴县| 天峻县| 日照市|