Asdfasf

Wednesday, August 20, 2014

EJ-1 Consider Static Factory Methods instead of Constructors

Ref: Effective Java by Joshua Bloch

In Item-1 of Effective Java, Mr. Bloch emphasize why and how it is important to use Static Factory methods instead of constructors.

Here is goofy and wasteful way to get Boolean instances
public Boolean getFalse(){
return new Boolean(false);
}
public Boolean getTrue(){
return new Boolean(true);
}

Here is shiny and frugally way to get immutable Boolean instance with static factory method
public static Boolean valueOf(boolean b){
return b ? Boolean.TRUE : Boolean.FALSE;
}


Lets go over advantages of using static factory methods
1.) Unlike constructors, the have names. If parameters to a constructor do not describe object being returned, a static factory with well choosen name is easier to use and resulting client code easier to read.
public BigInteger(int, int, Random){}
//which returns a BigInteger that is probably prime
//would have been better expressed as a static factory method
public static BigInteger probablePrime(int, int, Random){}


Another example is multiple constructors with same signature as I met in stackoverflow.
Two constructors with same signature doing different things.

public class Arquivo {
private File diretorio = null ;
public Arquivo(File dir){
this.diretorio = dir;
}
public Arquivo(String dir){
this( new File(dir) );
}
public Arquivo(String fileName){
this( new File("./src/Data/"+fileName) );
}
}
view raw Arquivo.java hosted with ❤ by GitHub


Can be managed by using static factory methods.

public class Arquivo {
private File diretorio = null ;
private Arquivo(File dir){
this.diretorio = dir;
}
public static Arquivo newInstanceByFile(File dir){
return new Arquivo(dir);
}
public static Arquivo newInstanceByFilePath(String path){
return new Arquivo(new File(path) );
}
public static Arquivo newInstanceByFileName(String name){
return new Arquivo(new File("./src/Data/"+fileName));
}
}
view raw Arquivo2.java hosted with ❤ by GitHub


2.) Unlike constructors, they are not required to create a new object each time they're invoked. This is demonstrated as in boolean example above and important to use system resources frugally by avoiding unnecessary instance creation.

3.) A third advantage of static factory methods is that, unlike constructors, they can return an object of any subtype of their return type. Mr Bloch exemplifies this advantage with Service Provider Framework pattern.

public interface Provider {
Service newService();
}
public interface Service {
// Service-specific methods go here
}
public class Services {
private Services() {} // Prevents instantiation (Item 4)
// Maps service 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 registerDefaultProvider(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 p = providers.get(name);
if (p == null)
throw new IllegalArgumentException(
"No provider registered with name: " + name);
return p.newService();
}
}


Finally, he give a list of some common method names to statis factory methods.
  • valueOf
  • of
  • getInstance
  • newInstance
  • getType
  • newType
Often static factories are preferable, so avoid the reflex to provide public constructors without first considering static factories.