Now imagine the instance requires very specific, customized configurations (VPC subnets, IAM roles, block storage). A Factory would require a constructor with 15 parameters. Instead, we use a Builder.

  1. The Complex Object
public class CustomEC2Instance {
    private final String amiId;
    private final int rootVolumeSize;
    private final String iamRole;

    // Private constructor - forces you to use the Builder
    private CustomEC2Instance(Builder builder) {
        this.amiId = builder.amiId;
        this.rootVolumeSize = builder.rootVolumeSize;
        this.iamRole = builder.iamRole;
    }
  1. The Builder (Assembling piece by piece)
    public static class Builder {
        private String amiId;
        private int rootVolumeSize;
        private String iamRole;

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

        public Builder withStorage(int sizeInGb) {
            this.rootVolumeSize = sizeInGb;
            return this;
        }

        public Builder withRole(String role) {
            this.iamRole = role;
            return this;
        }

        public CustomEC2Instance build() {
            return new CustomEC2Instance(this);
        }
    }
}
  1. Usage: Step-by-step configuration
CustomEC2Instance server = new CustomEC2Instance.Builder()
    .withAmi("ami-0abcdef1234567890")
    .withStorage(100)
    .withRole("S3-Access-Role")
    .build();