blob: b42c246de74f4bccd2c188a3f3cda1a3760cfed4 [file] [log] [blame] [view] [edit]
**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()`