- 1. Use static factory method instead of constructor
- 2. Consider a builder when faced with many constructor parameters
- 3. Enforce the singleton property with a private constructor or an enum type
- 4. Enforce noninstantiability with a private constructor
- 5. Avoid creating unnecessary objects
- 6. Eliminate obsolete object references
- 7. Avoid using Finalizers
1. Use static factory method instead of constructor
Class should provide a public static factory method. It is a static method returing an instance.
Pros: compare to constructor
- Easy to customize name, like
BigInteger.probablePrimeto return prime numbers
- No need to create new object when called.
- Able to return subclass instance
- Classes without public or protected constructors cannot be subclassed.
- They are not readily distinguishable from other static methods.
java.util.Collections have 32 static factory methods
The class of the object returned by a static factory method need not even exist at the time the class containing the method is written. Such flexible static factory methods form the basis of service provider frameworks. It is such kind of a system: multiple service provider implement one service, the system provide multiple implementation for client, and decouple them from implementations. A service provider frameworks have three important components:
- Service Interface: implement the functionality
- Provider Registration API: client register the service
- Service Access API: client get service instance
and one optional component:
- Service Provider Interface: for provider to create the implementation of service.
Take JDBC as an example,
Connection is the service interface,
DriverManager.registerDriver is the provider registration API,
DriverManager.getConnection is the service access API, and
Driver is the service provider interface.
2. Consider a builder when faced with many constructor parameters
Don't write telescoping constructor pattern, because it is hard to write client code when there are many parameters, and harder still to read it
One parameterless constructor to create the object, and the call setter methods to set each required parameter and each optional parameter of interest.
- If construction process is split across multiple calls, a JavaBean may be in an inconsistent state partway through its construction.
- JavaBeans pattern precludes the possibility of making a class immutable, because of setters.
Client use required parameters to call the constructor(or static factory method) to get a builder object. Then client config the builder, and call the
build method to create the immutable instance.
For creating a NutritionFacts object
A builder whose parameters have been set makes a fine Abstract Factory. Client can pass such a builder to a method to enable the method to create one or more objects for the client.
For example, we need to create a tree.
3. Enforce the singleton property with a private constructor or an enum type
To make a singleton class that is implemented using either of the previous approaches serializable, it is not sufficient merely to add
implements Serializable to its declaration. To maintain the singleton guarantee, you have to declare all instance fields
transient and provide a
readResolve method. Otherwise, each time a serialized instance is deserialized, a new instance will be created, leading to spurious
Elvis sightings. To prevent this, add this
readResolve method to the
As on release of Java 1.5, there is a approach to implementing singletons
It provides the serialization machinery for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks. Now it is the best way to implement a singleton.
4. Enforce noninstantiability with a private constructor
5. Avoid creating unnecessary objects
Try to use static factory method on immutable class, or mutable variables that known will not be changed.
A method to check whether a person is born during baby boom. It will actually check whether the person was born between 1946 to 1964.
Instead, we can do:
This is program is slow. We should change
The princeple is to reuse those objects that cost a lot to create as many times as possible.
6. Eliminate obsolete object references
If a stack grows and then shrinks, the objects that were popped off the stack will not be garbage collected, even if the program using the stack has no more references to them. This is because the stack maintains obsolete references to these objects. An obsolete reference is simply a reference that will never be dereferenced again. If an object references is unintentionally retained, not only is that object excluded from garbage collection, but so too are any objects referenced by that object, and so on.
One way to resolve this is: null out references once they become obsolete.
When to null out the reference?
Whenever a class manages its own memory. the programmer should be alert for memory leaks. Whenever an element is freed, any object references contained in the element should be nulled out.
Storage Pool contains elements array. Array space is allocated, but elements inside is unknow to the garbage collector.
Another source of memory leak is listeners and callbacks. Listeners need to be deregistered when not used any more.. The best way to ensure that callbacks are garbage collected promptly is to store only weak references to them, for example, by storing them only as keys in a
7. Avoid using Finalizers
Using finalizer will lead to unstatble, low performance, and portability problems.
The problem of finalizer is that the time to run it is unpredictable. It is not even guarantee that the finalizer will be run.
One more problem is: it is about 430 times slower to create and destroy objects with finalizer.
Provide an explicit termination method, and require clients of the class to invoke this method on each instance when it is no longer needed. Use try..catch..finally.
Act as a "safety net" in case the owner of an object forgets to call its explicit termination method
The finalizer should log a warning if it finds that the resource has not been terminated
The four classes cited as examples of the explicit termination method pattern (FileInputStream, FileOutputStream, Timer and Connection) have finalizers that serve as swafy nets in case their termination methods aren't called.