Controlling Instantiation

A constructor provides a way to create an instance of a class.  Sometimes we may want to prohibit creating instances of the class or provide alternate ways to create instances of the class.

Contents

Non-instantiable Classes

Some classes should not be instantiated.  For example, classes that have only static fields and methods should not be instantiated.  In such a case, we should prohibit instantiation by making the default constructor private.

public class Foo {
    public static final int MAXSIZE = 10;
    private Foo() {}
    ...
}

Singleton Classes

If a class allows only one instance of it in existence at any point in time, we say the class implements the singleton pattern.  The preferred method of creating a singleton class to use an enumerated class. Users are then not allowed to create additional instances of the class.

public enum Foo {     
    INSTANCE;     

    public void method1() {...} 
    ....
}

Access to the single instance is through the enumerated class.

Foo singleton = Foo.INSTANCE;
singleton.method1();

Static Final Fields

Another way to create a singleton class is to create a class and

  1. make the default constructor private
  2. create a static final field that holds a reference to the single instance
public class Foo {
    public static final Foo INSTANCE = new Foo();

    private Foo() { }
    ...
    public void method1() {...}
}

Access to the single instance is through the static field INSTANCE.

Foo singleton = Foo.INSTANCE;
singleton.method1();

Static Factory Method with Static Final Fields

Another approach is to make the static field private and to provide a static method that returns the singleton instances.

public class Foo {
    private static final Foo INSTANCE = new Foo();
    private Foo() { }
    
    public static Foo getInstance() { return INSTANCE; }
    ...
    public void method1() {...}
}

Access to the singleton instance is through the static factory method getInstance.

Foo singleton = Foo.getInstance();
singleton.method1();

A disadvantage to using an enumerated class or a class without a public or protected constructor is that they can not be extended.

Static Methods with a Cache

There are times when we need to manage a bounded set of instances of a class.  Static factory methods are not required to return a new instance of a class like constructors do.  This allows us to create a cache of instances.  The static factory method can return a shared instance, an unused instance in the cache, or no instance at all (null).

More on Static Factory Methods

We may want to use static factory methods even when we don’t need to limit the number of instances of a class.  Static factory methods can

  1. have meaningful names, unlike constructors
  2. return any object of any subtype or implemented interface

The latter reason, we’ll see later, is important as it helps us implement interface-based frameworks.

© 2017 – 2019, Eric. All rights reserved.