Consider static factory methods instead of constructors

Sunday, April 30, 2017 Unknown 0 Comments




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: