When designing classes you usually have to decide between:
- providing a “full” constructor that takes the initial values for all required fields as arguments: clumsy to use but guarantees fully initialized and valid objects
- providing just a “default” constructor and accessors for all necessary fields: might be convenient sometimes but does not guarantee that all members are properly initialized before some critical methods are called.
- a mixed approach (more code, more work, can’ eliminate the “not fully initialized” problem)
I have seen several APIs and frameworks that use one of the above or even an inconsistent approach that differs from class to class. What are your thoughts and best practices on that subject?
The short answer is that an object should be fully initialized after its constructor was called.
This should be the default approach with the least surprises for users. There are cases when your run-time, framework or other technical constraints prevent the default approach.
In some circumstances a the Builder pattern helps to support cases when it is not possible to use a simple constructor. This approach is in the middle ground, letting users call setters to initialize and still be able to work only with fully initialized objects.
A static factory method is appropriate in cases when the object constructor needs to be more flexible than a constructor but a builder is too complex to implement.
Constructor:
Setter:
Builder:
Static factory method:
All four approaches will produce an instance, x, of class X.
Constructor
Pros:
Cons:
new X(a = "a", b = "c"))Setter
Pros:
Cons:
Builder
Pros:
Cons:
Static factory method
Pros:
Cons: