**Design:** Convention, **Status:** [Accepted](README.md) ## Favor Static Factory Methods Over Constructors This page describes the structures and conventions used to initialize a class. ### Static Factory Methods vs. Constructors Static factory methods are preferable than constructors for the following reasons: - Static factory methods provide meaningful names compared with constructors, which improves the readability of the codes by describing the objects being returned. ```java // With static factory method, giving a hint that a foobar provider with default settings is being created. FoobarProvider defaultProvider = FoobarProvider.defaultFoobarProvider(); // With constructor FoobarProvider defaultProvider = new FoobarProvider(); ``` - They are useful when work with immutable classes as we can reuse the same object instead of creating new object every time when it is invoked. - Static factory methods can return any subtype of that class and this gives us flexibility to write a separate factory class to return different subclasses if needed. There are a few disadvantages of static factory methods: - It might not be straightforward for the users to use static factory method to create new instances compared with constructors, but this can be improved by providing a set of common method names such as `create()` and smart IDEs such as IntelliJ and Eclipse can also give hints and help auto-completing. - Classes without public or protected constructors cannot be subclassed, but this could encourage us to use composition instead of inheritance. In general, we should favor static factory methods over constructors. ### Example ```java public class DefaultCredentialsProvider implements AwsCredentialsProvider, SdkAutoCloseable { private static final DefaultCredentialsProvider DEFAULT_CREDENTIALS_PROVIDER = new DefaultCredentialsProvider(builder()); private DefaultCredentialsProvider(Builder builder) { this.providerChain = createChain(builder); } public static DefaultCredentialsProvider create() { return DEFAULT_CREDENTIALS_PROVIDER; } public static Builder builder() { return new Builder(); } public static final class Builder { // ... } // ... } // There are two ways to create new instance DefaultCredentialsProvider defaultCredentialsProvider1 = DefaultCredentialsProvider.create(); DefaultCredentialsProvider defaultCredentialsProvider2 = DefaultCredentialsProvider.builder().build; ``` ### Naming Conventions The naming conventions for the static factory methods: - `create()`, `create(params)` when creating a new instance eg: `DynamoDBClient.create()` - `defaultXXX()` when returning an instance with default settings. eg: `BackoffStrategy.defaultStrategy()`