views:

458

answers:

4

I have some classes that are used as Singletons. They share some basic functionality and extend the same ancestor from a library which in turn isn't normally used as a Singleton.

If I put the common functionality in a base class that inherits from the common ancestor, I get a class which makes no sense to instantiate, so I made it abstract. Also, because the classes are all used as Singletons, they should all have an init() and a getInstance() method, which are both static. All the constructors are of course non-public.

Now, since static is an illegal modifier for abstract methods, the following doesn't work, although this would be exactly what I want:

class Base extends LibraryClass {
    protected Base() {
        // ... constructor
    }

    // ... common methods

    // ILLEGAL!
    public static abstract void init();
    public static abstract <T extends Base>T getInstance();
}

class A extends Base {
    private static A _INSTANCE;

    private A() {
        super();
    }

    public static void init() {
        _INSTANCE = new A();
    }

    public static A getInstance() {
        return _INSTANCE;
    }
}

I could just leave out the illegal lines in the base class and be done with it. But how do I express that every child of Base must have these methods?

+1  A: 

You can't express that child classes have specific static methods.

In fact there should be no need to do this as the static methods will only be called directly on the child classes (A.init() and A.getInstance() in your example) and never through a reference to the base class (i.e. static methods do not support polymorphism).

Matthew Murdoch
+6  A: 

This is not possible in Java. Existence of static methods can't be enforced; neither by abstract nor by using an interface.

My solution was to use IoC in a way: I created a factory class for singletons. It would save the singletons in a map. The key would be the class. This way, I could say:

A singleton = Factory.create (A.class);

The major advantage of this design: I can create a Factory.replace() method where test cases can override the singletons.

Aaron Digulla
Why do we need Singleton even though we already have Static or Final in Java? What is the major resign/cause which force us to adopt "Singleton" instead of "Static, Final"? Although to achieve Singleton we use Static. I couldn't understand this puzzle. Please pass your comments.
Garhwali Bhai
static final is for constants which are created eagerly. A singleton is usually created lazy (only when it is needed). Also, static final doesn't allow to replace the "constant" with a mockup. Therefore, they make testing hard or even impossible.
Aaron Digulla
See http://stackoverflow.com/questions/11831/singletons-good-design-or-a-crutch
Aaron Digulla
+1  A: 

Why don't you go all the way and make your factory (in the base class) pass in a parameter indicating which sub-class you want it to return. There are lots of advantages to doing it that way, and few disadvantages.

The way you are trying to do it doesn't make a whole lot of sense since static methods don't deal with inheritance in quite the same way as normal methods.

Bill K
+1  A: 

A common way to deal with adding singleton semantics to a class for which it may be inconvenient to add the semantics correctly is to implement the singleton functionality in a wrapper class. For example:

public class UsefulThing {

}

public final class SingletonOfUsefulThing {
    private static UsefulThing instance;

    private SingletonOfUsefulThing() {}

    public UsefulThing getInstance() {
        if (instance == null) {
            instance = new UsefulThing(); 
        }

        return instance;
    }
}

This allows you to give some of the primary singleton benefits to a class without some of the consequences that implementing the singleton semantics in the class directly forces you to deal with and allows some room for changing the specific type of the class you're exposing as a singleton (via using a factory to create the instance, for example, instead of new.

Paul Morie