Consider static factory methods instead of constructors
The
normal way for a class to allow a client to obtain an instance of
itself is to provide a public constructor. There is a technique that
should be a part of every programmer toolkit. A class can provide
public static factory method, which is simply a static method that
returns an instance of the class.
Note
– Static factory method is
not the same as the factory method
pattern from Design patterns.
A
class can provide its clients with static factory method instead of,
or in addition to constructors. Providing a static
factory method instead
of a public constructor has both advantages and disadvantages.
Advantages
-
1
. Unlike constructors they have names.A static factory method with a
well chosen name is easier to use and the resulting code easier to
read. For example the constructor BigInteger(int, int, Random), which
returns a BigInteger that is probably prime, would have been better
expressed as a static factory method named as
BigInteger.probablePrime(int,
int, Random)(This method was eventually added in the 1.4 release).
A
class can have only a single constructor with a given
signature.Programmers have been known to get around this restriction
by providing two constructors whose parameter lists differ only in
the order of their parameter types.This is real bad. User of such a
API will never be able to remember which constructor is which and
will end up calling the wrong one by mistake. People reading code
that uses constructors will not know what the code does without
referring to the class documentation.
2
. They are not required to create new instance each time they are
invoked.This allows immutable classes to use preconstructed
instances, or to cache instances as they're constructed and dispense
them repeatedly to avoid creating unnecessary duplicate objects.
It
can greatly improve performance if equivalent objects are requested
frequently, especially if they are very expensive.
The
ability of static factory methods to return the same object from
repeated invocations allows classes to maintain strict control over
what instances exist at any time. Classes that do this are called
instance-controlled. Instance controlled class allows a class
to guarantee that it is a singleton or non instantiable. Also it
allows an immutable class to make guarantee that no two equal
instances exist: object1.equals(object2) if and only if
object1==object2. If a class makes this guarantee, then its clients
can use the (==) operator instaed of calling equals, which may result
in improved performance. Enum type provide this guarantee.
3
. Unlike constructors they can return an object of any subtype of
their return type. This gives you great flexibility in choosing the
class of returned type. This technique lends itself to
interface-based frameworks , where interfaces provide natural return
types for static factory methods. Using such a factory method
requires the client to refer to the returned object by its interface
rather than its implementation class, which is generally a good
practice.
Example
given below will explain above points.
//
A service interface
public interface Service { // methods go here }
//
A service provider interface
public interface Provider { Service newService(); }
//
Non instantiable class for service registration and access
public class Services { private Services(){ } // prevent creating instances //Maps services names to services private static final Map<String,Provider> providers=new ConcurrentHashMap<String, Provider>(); public static final String DEFAULT_PROVIDER_NAME = "def"; //Provider registration API public static void registerDefualtProvider(Provider p){ registerProvider(DEFAULT_PROVIDER_NAME,p); } public static void registerProvider(String name, Provider p){ providers.put(name,p); } //Service access API public static Service newInstance(){ return newInstance(DEFAULT_PROVIDER_NAME); } public static Service newInstance(String name){ Provider provider=providers.get(name); if(provider==null){ throw new NullPointerException("No provider matching this name"); } return provider.newService(); } }
Disadvantages
-
The
main disadvantage of providing only static factory method is that
classes without public or protected constructors can not be
sub classed.
Second
disadvantage of using static factory method is that they are not
easily distinguishable from other static methods. They do not stand
API documentation in the way that constructors do, so it can be
difficult to figure out how to instantiate a class that provides
static factory methods instead of constructors.
0 comments: