javaadvanced

Type-Safe Step Builder Pattern

Enforce required fields at compile time with a step builder: each step returns the next interface.

java
public class StepBuilderDemo {

    // The target object
    record HttpRequest(
        String method,
        String url,
        java.util.Map<String, String> headers,
        String body,
        int timeoutMs
    ) {}

    // Step interfaces — enforces order at compile time
    interface MethodStep { UrlStep method(String method); }
    interface UrlStep { BuildStep url(String url); }
    interface BuildStep {
        BuildStep header(String key, String value);
        BuildStep body(String body);
        BuildStep timeout(int ms);
        HttpRequest build();
    }

    // Single implementation
    static class HttpRequestBuilder implements MethodStep, UrlStep, BuildStep {
        private String method;
        private String url;
        private final java.util.Map<String, String> headers = new java.util.LinkedHashMap<>();
        private String body;
        private int timeoutMs = 30_000;

        private HttpRequestBuilder() {}

        static MethodStep create() { return new HttpRequestBuilder(); }

        @Override
        public UrlStep method(String method) {
            this.method = method;
            return this;
        }

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

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

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

        @Override
        public BuildStep timeout(int ms) {
            this.timeoutMs = ms;
            return this;
        }

        @Override
        public HttpRequest build() {
            return new HttpRequest(method, url,
                java.util.Collections.unmodifiableMap(headers), body, timeoutMs);
        }
    }

    public static void main(String[] args) {
        // Compile-time safety: must call method() → url() → then optional steps
        HttpRequest get = HttpRequestBuilder.create()
            .method("GET")
            .url("https://api.example.com/users")
            .header("Accept", "application/json")
            .timeout(5000)
            .build();

        HttpRequest post = HttpRequestBuilder.create()
            .method("POST")
            .url("https://api.example.com/users")
            .header("Content-Type", "application/json")
            .header("Authorization", "Bearer token123")
            .body("{\"name\": \"Alice\"}")
            .build();

        System.out.println(get);
        System.out.println(post);

        // This WON'T compile — enforces order:
        // HttpRequestBuilder.create().url("...");
        // HttpRequestBuilder.create().method("GET").build();
    }
}

Use Cases

  • Enforcing required fields at compile time
  • Fluent API design with mandatory steps
  • Complex object construction with validation

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.