See JavaSingletonProblems for a list of problems related to Singletons in Java
I was writing an abstract class to act as a superclass for singletons which get their data from the application database. It was all going fine until I started using two subclasses.
The superclass had a protected static variable as the unique instance. I was expecting each subclass to inherit this and have their own static variable. But no, they shared the same one, so they overwrote each other.
How can I get around this? Is there any way to have a superclass that I can extend to create singletons?
-- JoshSacks
From: JavaSingletonClass
Do singletons have so much in common that we can justify making them inherit from one base class? Can they be used in a common way? Do they represent the same type? In Java, there is only single inheritance, why to waste it for this? You will never need code like:
if (x instanceof Singleton) ...or
(Singleton) xBesides, the nice feature of singletons is that the code which uses the singleton, does not need to know, the object is a singleton. (Otherwise we cound use static class method instead of singletons) I believe, an abstract base class for Singletons is prime example of PrematureGeneralization. So it not an improvement at all.
If we see a class/type as a group of objects which are similar and behave the same way, then it is just weird to group objects into one class just because each of them is in a group of one. Some sort of class of objects which want to be alone in one's class :-)
-- GregorRayman
The only idea I've had for this problem looks something like this (from my head, not compiled & tested):
public abstract class Singleton { private static Hashtable instances = new Hashtable();// should this not be protected? -- ThomasSchodt public static Singleton getInstance() throws Exception { if (!instances.has_key(getClass()) instances.put(getClass(), getClass().createInstance()); return instances.get(getClass()); } }Blech. Maybe someone else can do better. -- WayneConrad
(Sorry. You can't call getClass() from a static method.) --JoshSacks
Indeed. You can, however, roll your own. private static final Class myClass = new SecurityManager() { public Class getClass1(){return getClassContext()[1];} }.getClass1(); public static Class getClass1() { return myClass; } Only it does not inherit well. -- ThomasSchodtIt's very hard to do better than that. On the other hand, Singleton is a pattern, and one of the characteristics of patterns is that it's often hard to create them as reusable classes (else they'd be utility classes, not patterns). The "overhead" code for a Java singleton is small and easy to write, and there are good reasons to avoid having many singletons in a system. --GlennVanderburg
That matches my perception. Contrast the above with a raw, stand-alone Singleton:
class C { private C instance; private C() {...} public C getInstance() { if (instance == null) instance = new C(); return instance; } }It gets more complex, not less, with a base class.
In C++, however, you can create wonderific templates for Singletons. -- WayneConrad
This is true, you essentially get a different class object for each Singleton template instantiation. I wonder if you can do this with GenericJava? -- RobertDiFalco
What is it that requires the base class to have both the singleton behavior and the common behavior of the subclasses? It doesn't really make sense for an abstract class to be a singleton since you can't instantiate it. Have the base class define the common behaviors and the subclasses have the instance object. What does the getInstance() method return anyway? The base class?
But anyway, this is Java, so there's nothing wrong with this:
public abstract class Foo { public Foo getInstance() ... other methods ... } public class Bar { private static Bar _theInstance; public Foo getInstance() { if (_theInstance == null) { _theInstance = new Bar(); } return _theInstance; } } public class Baz { private static Baz _theInstance; public Foo getInstance() { if (_theInstance == null) { _theInstance = new Baz(); } return _theInstance; } }-- StevenNewton
Steven, I agree. Consider the following:
public abstract class SomeManager { abstract public void doSomething(); public static SomeManager getInstance() { if ( m_instance == null ) m_instance = getDefaultInstance(); return m_instance; }One problem here is that the compiler will complain because m_instance is not defined in SomeManager. But otherwise this solution is fine and converges nicely with mine.
protected static SomeManager getDefaultInstance() { String sClass = System.getProperty( "my.manager" ); try { return Class.forName( sClass ); } catch ( ClassNotFoundException? e ) { return new DefaultConcreteManager(); } } }The idea being that there is some property file or something that tells us what concrete SomeManager implementation the system would like us to use. One shouldn't have to explicitly name the class object of the concrete manager, just its abstract base. Client code should be able to simply type:
SomeManager.getInstance().doSomething();This is like SecurityManager. We just want to get the system security manager, we don't need to know if it was specialized or not. In fact, it would be bad if we did know. Usually this method works fine if there is only going to be only one instance of any SomeManager class. But if you want each subclass to be a potential singleton, you've got problems. However, I would say that the InheritedJavaSingletonProblem isn't a Java problem as much as it is a design problem.
Therefore: Each class object that receives a getInterface message should have its own static instance variable.
SomeManager.getInstance();Only one subclass of Manager can define a singleton instance. Calling SomeManagerA.getInstance() would not give us a different singleton than calling SomeManagerB.getInstance(). If you do want A and B to have difference singletons then they should each override the static getInstance memeber from SomeManager.
Exactly Robert -- you put it more succinctly than I. - sn
Thanks very much for all this. I was sure there must have been an easy answer, so in a way I'm relieved that there isn't. I can stop worrying about it now, and just write them all separately. -- JoshSacks
I think I don't get the stuff about Singleton and subclassing, and in particular protecting the constructor.
Consider the following class:
class Singleton { protected static Singleton instance; protected Singleton() { super(); } public Singleton getInstance() { if (instance == null) instance = new Singleton(); return instance; } }The constructor is protected, to prevent clients from making umpteen instances. But a malicious programmer could make a subclass of Singleton, and access the constructor multiple times:
class BadSingleton? extends Singleton { protected BadSingleton?() { super(); } public Singleton getInstance() { return new Singleton(); } }The getInstance() method here is broken; multiple instances of the superclass will be constructed. How can I prevent classes like this from being written? I can't make the constructor private; then subclasses are prevented altogether. -- JeremyGibbons
I suggest that if you are worried that malicious programmers do this, then you have much bigger problems than a screwed up singleton. -- MarkAddleman
As I see your example, it is wrong. You forgot that the getInstance() method should be static, hence is not overwriteable (at least not in Java). -- AlfSchiefelbein
The basic problem with all this is that a class, in java, is not a "real" object. Static methods are simply procedures, bound by name to their class. Because there is no genuine class object, there is therefore no place to hang a class instance variable, and so the InheritedJavaSingletonProblem arises. It is just one member of a family of related problems.
I've built an environment I call "Clazzy", in which I essentially cloned the Smalltalk metastructure into java. I have added an abstract base class that plays the role of "Object", and everything descends from this. That class defines a field named "kind" that functions exactly like a class object in Smalltalk. I have written a small infrastructure that is currently mostly braindamaged that connects each Kind to its corresponding Java class, so that Kind methods simply delegate to their (Java) class. These delegators, however, hang on real objects with real inheritance. Since each Kind is a genuine class, it may have instance variables (which behave like class instance variables in Smalltalk).
The fun stuff, though, is that instance creation, class methods, class instances, and similar things all behave as in Smalltalk. It makes AbstractFactory, for example, as easy in java as it is in Smalltalk.
All in all, I would describe this as a curiosity more than a real environment, but if there's interest, I think it could be readily transformed into something more useful. If anybody is interested, let me know.
-- TomStambaugh
For what its worth, you can do this in C++:
template <typename T> class Singleton { public:
static T *Get() { if( !inst ) inst = new T(); return inst; }protected:
Singleton() {}private:
static T *inst;};
template <class T> T *Singleton<T>::inst = 0;
class X : public Singleton<X> {
// ... // X is already a singleton // add its behaviour here};
Cool eh?
But not if you're using Java :). Sorry guys.
But you're not using Java. :(. Sorry guy.
I'm not sure what it means to be an abstract Singleton. You have to ask yourself why you need this parent to be a singleton. Depending on how you answer the question, the solution to your problem lies in either creating a FactoryMethod that returns (and creates if necessary) the correct concreate subclass; or in removing the singleton from the abstract superclass and instead having all the concrete children be Singletons.
template<class T> class Singleton {
protected: T *&pointer(void) { static T *p=0; return p; } public: T &instance(void) { if (!pointer()) pointer=new T(); return *pointer(); }}
This uses the fact that the static variable lives in the function, and since there is a new "pointer" function written each time the Singleton is created for a new type, there will be a new static pointer created. And this happens without needing to do it in a C file.
Now you can declare class X:public Singleton<X> as before...
Something along those lines might work bettwe with Java, but alas I don't really speak enough Java.
Too bad Java didn't define static to really mean metadata (as in ObjectiveCee or SmallTalk) in lieu of the Cee or CeePlusPluss? concept. Sometimes I wonder if Java is ObjectOriented enough.
I was surprised to find Java makes abstract Singleton classes so difficult.
I have an abstract class with some methods implemented and some not implemented. All subclasses of this MUST be singletons and it must be enforced in the structure, so that my system can request an instance of a subclass and be guaranteed it is the only copy.
I've come up with the following solution, which is a hybrid of various approaches I've seen on the net. I do not want to have a SingletonFactory? class. This approach allows the abstract class double as a factory for subclasses, because static methods on abstract classes CAN be called.
public abstract class AbstractSingleton? { private static final Map singletonRegistry = new HashMap(); public static final synchronized Singleton getInstance(Class cls) { Singleton instance = (Singleton)singletonRegistry.get(cls); if (instance == null) { if (!Singleton.class.isAssignableFrom(cls)) throw new IllegalArgumentException("Singleton: getInstance: Class " + cls.getName() + " is not a subclass of AbstractSingleton?."); try { instance = (Singleton)cls.newInstance(); } catch(Exception ex) { System.out.println("Singleton: getInstance: Could not instantiate object for " + cls.getName() + ": " + ex.getMessage()); } if (instance != null) { singletonRegistry.put(cls, instance); System.out.println("Singleton: getInstance: Registered singleton " + cls.getName() + "."); } else System.out.println("Singleton: getInstance: Could not register singleton " + cls.getName() + "."); } return instance; } // Other methods... }If concrete classes which extend this class (e.g. ConcteteSingleton?) are defined in the same package as AbstractSingleton? and if their constructors have default access, the only way to obtain an instance of a subclass from outside the package is through AbstractSingleton? using a call like:
Singleton singleton = AbstractSingleton?.getInstance(ConcreteSingleton?.class);I know this uses reflection to create instances, and reflection is slow, but since we are dealing with singletons it only happens once per singleton so I can live with it.
By the way, the reflection used expects a argumentless constructor in singleton subclass - if your constructors take arguments you'll have to use more advanced reflection code. --NiallGallagher