When to Use a Constructor and When to Use Getinstance() Method (Static Factory Methods)

When to use a Constructor and when to use getInstance() method (static factory methods)?

Everybody seems to focus on singletons while I think that the question is actually about constructor vs static factory methods.

This is actually Item 1: Consider static factory methods instead of constructors of Effective Java by Joshua Bloch:

Item 1: 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 another technique that should
be a part of every programmer’s
toolkit. A class can provide a public
static factory method, which is simply a static method that returns an
instance of the class. Here’s a simple
example from Boolean (the boxed
primitive class for the primitive type
boolean). This method translates a
boolean primitive value into a
Boolean object reference:

public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}

Note that a static factory method is
not the same as the Factory Method
pattern from Design Patterns
[Gamma95, p. 107]. The static factory
method described in this item has no
direct equivalent in Design
Patterns
.

A class can provide its clients with
static factory methods instead of, or
in addition to, constructors.
Providing a static factory method
instead of a public constructor has
both advantages and disadvantages.

Advantages (quoting the book):

  • One advantage of static factory methods is that, unlike constructors, they have names.
  • A second advantage of static factory methods is that, unlike constructors, they are not required to create a new object each time they’re invoked.
  • A third advantage of static factory methods is that, unlike constructors, they can return an object of any subtype of their return type.
  • A fourth advantage of static factory methods is that they reduce the verbosity of creating parameterized type instances.

Disadvantages (still quoting the book):

  • The main disadvantage of providing only static factory methods is that
    classes without public or protected constructors cannot be subclassed.
  • A second disadvantage of static factory methods is that they are not
    readily distinguishable from other static methods.

Static factory methods vs Instance (normal) constructors?

In Effective Java, 2nd edition, Joshua Bloch certainly recommends the former. There are a few reasons I can remember, and doubtless some I can't:

  • You can give the method a meaningful name. If you've got two ways of constructing an instance both of which take an int, but have different meanings for that int, using a normal method makes the calling code much more readable.
  • A corollary of the first - you can have different factory methods with the same parameter list
  • You can return null for "potentially expected failure" cases whereas a constructor will always either return a value or throw an exception
  • You can return a type other than the declared (e.g. return a derived class)
  • You can use it as a factory, to potentially return a reference to the same object several times

The downsides:

  • It's not as idiomatic, currently - developers are more used to seeing "new"
  • If you see "new" you know you're getting a new instance (modulo the oddity I mentioned recently)
  • You need to make appropriate constructors available for subclasses
  • In C# 3, constructor calls are able to set fields/properties in a compact manner with object initializer expressions; the feature doesn't apply to static method calls

Do we ever need to prefer constructors over static factory methods? If so, when?

static factories still have to call a constructor in the end. You can move most of the functionality into the static factory, but you cannot avoid using a constructor.

On the other hand for simple cases, you can have just a constructor without having a static factory.

Constructors are the only way to set final fields, which IMHO are preferable to non-final fields.

You can use constructors can in sub-classes. You cannot use static factories for a sub-class.

If you have a good dependency injection framework to build dependencies of a component, you may find that static factories don't add much.

How to use Static factory methods instead of constructors?

See here for a nice exposition of the main reasons you might want to do this. In summary:

  1. Named "constructors".
  2. Can return null, if appropriate.
  3. Can return an instance of a derived class, if appropriate.
  4. Reduce verbosity when instantiating variables of generic types.

Another reason comes to mind that the article doesn't mention: Can implement interesting logic to avoid creating new objects all the time (caching based on parameters, recycling, etc.).

What are static factory methods?

We avoid providing direct access to database connections because they're resource intensive. So we use a static factory method getDbConnection that creates a connection if we're below the limit. Otherwise, it tries to provide a "spare" connection, failing with an exception if there are none.

public class DbConnection{
private static final int MAX_CONNS = 100;
private static int totalConnections = 0;

private static Set<DbConnection> availableConnections = new HashSet<DbConnection>();

private DbConnection(){
// ...
totalConnections++;
}

public static DbConnection getDbConnection(){

if(totalConnections < MAX_CONNS){
return new DbConnection();

}else if(availableConnections.size() > 0){
DbConnection dbc = availableConnections.iterator().next();
availableConnections.remove(dbc);
return dbc;

}else {
throw new NoDbConnections();
}
}

public static void returnDbConnection(DbConnection dbc){
availableConnections.add(dbc);
//...
}
}

Consider providing static factory methods insteads of constructors

This chapter from the book Effective Java explains it well: Consider Static Factory instead of Constructors. It explains all the pros and cons for both of them in the best way you can understand.

Just to quote the advantages and disadvantages from the book:

Advantages:

  • One advantage of static factory methods is that, unlike constructors, they have names.
  • A second advantage of static factory methods is that, unlike constructors, they are not required to create a new object each time they’re invoked.
  • A third advantage of static factory methods is that, unlike constructors, they can return an object of any subtype of their return type.
  • A fourth advantage of static factory methods is that they reduce the verbosity of creating parameterized type instances (This one can be ignored in Java 7)

Disadvantages:

  • The main disadvantage of providing only static factory methods is that classes without public or protected constructors cannot be subclassed

  • A second disadvantage of static factory methods is that they are not readily distinguishable from other static methods.

You can study them in more detail in the link I gave.

Should I always use static factory methods instead of constructors?

In general, constructors are simpler than Factories, so this is a major reason to choose constructors over Factory. Use Factory when the situation calls for it, no "by default". You should do the simplest thing that solves your problem, and most of the time this would be constructors.

Is it better practice to use static factory methods over an interface implemented by many different objects?

The question which you are thinking is answered in the famous book. Effective Java, 3rd Edition by Joshua Bloch. Note that Joshua Bloch is also developer of multiple Java SE classes as well.

Quoting from the book:

ITEM 1: CONSIDER STATIC FACTORY METHODS INSTEAD OF CONSTRUCTORS

Joshua gives following reasons for using static factory method in place of the constructors

  • One advantage of static factory methods is that, unlike constructors, they have names
  • A second advantage of static factory methods is that, unlike constructors, they are not required to create a new object each time
    they’re invoked.
  • A third advantage of static factory methods is that, unlike constructors, they can return an object of any subtype of their return
    type.
  • A fourth advantage of static factories is that the class of the returned object can vary from call to call as a function of the input
    parameters.
  • A fifth advantage of static factories is that the class of the returned object need not exist when the class containing the method is
    written.

Joshua also tells problems with the static factory methods

  • The main limitation of providing only static factory methods is that classes without public or protected constructors cannot be subclassed.

  • A second shortcoming of static factory methods is that they are hard for programmers to find.

Java.util.Collections can be seen as an example for static factory method. Quoting from the book

For example, the Java Collections Framework has forty-five utility
implementations of its interfaces, providing unmodifiable collections,
synchronized collections, and the like. Nearly all of these
implementations are exported via static factory methods in one
noninstantiable class (java.util.Collections). The classes of the
returned objects are all nonpublic.

Further the author echoes your thoughts

The Collections Framework API is much smaller than it would have been
had it exported forty-five separate public classes, one for each
convenience implementation. It is not just the bulk of the API that is
reduced but the conceptual weight: the number and difficulty of the
concepts that programmers must master in order to use the API. The
programmer knows that the returned object has precisely the API
specified by its interface, so there is no need to read additional
class documentation for the implementation class. Furthermore, using
such a static factory method requires the client to refer to the
returned object by interface rather than implementation class, which
is generally good practice (Item 64).

Java Standard Library makes extensive use of the static factory method because of the advantages suggested by Joshua Bloch. Another example is the valueOf function in the java.lang.Boolean class. The valueOf static factory method beautifully provide you the same object again and again (basically caching)

public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}

why use getInstance

It is associated with Singleton Pattern.

Many times there are also Factory Methods which help you in creating objects.

For example: Boolean.parseBoolean("true");

Advantages of Factory Methods are they are more verbose and easy to grasp than a series of constructors.



Related Topics



Leave a reply



Submit