I am currently on a project where we adopted the following structure :
Any class is instanciated from the environment via a ClassManager. The Class is therefore not reponsible for it's instanciation in a Singelton mode or not.
Firsly I would advise you to look deeply at the following links :
_ http://www.diasparsoftware.com/portfolio.html
Look at the "Use your singletons wisely"
_ http://www-106.ibm.com/developerworks/webservices/library/co-single.html
My advise from there is to bring one step further the typical Singleton : package test.lang.design_pattern.creational.singleton;
/**
* Singleton:
* Defines an instance operation that allows clients to access it's single instance
* @author ben@javacoder.net
* @date January 2002
*/
public class Singleton
{
private static Singleton instance; // own instance
/* protected to enable controlled subclassing */
protected Singleton()
{
}
public static Singleton getInstance()
{
// 'lazy' evaluate instance
if (instance == null)
instance = new Singleton();
return instance;
}
public void operation()
{
System.out.println("Singleton.operation() executing" );
}
}
with its client : package test.lang.design_pattern.creational.singleton;
/**
* Client:
* @author ben@javacoder.net
* @date January 2002
*/
public class Client {
public static void main(String[] args)
{
// use getInstance to obtain Singleton instance
Singleton s = Singleton.getInstance();
// use operation
s.operation();
}
}
To two classes now (Singleton & SingletonFactory) :
The Singletonnable file
package test.lang.design_pattern.creational.singleton.withFactory;
/**
* The purpose of this class is to "do something".
*
* @author <a href="mailto:tsmets@altern.org">Thomas SMETS, Brussels</a>
* @version 0.0.1 initial
*/
public class Singleton
{
/**
* This class is prefereably used as a <code>SingletonFactory</code> via a
* call to the <code>SingletonFactory</code>.
*
* @see SingletonFactory
*/
public Singleton ()
{
System.out.println ("public Singleton ()");
}
public void action ()
{
System.out.println ("Let's do something");
}
}
The Factory look is now like this :
package test.lang.design_pattern.creational.singleton.withFactory;
/**
* The purpose of this class is to :
* _ Help the Singleton class to become a real Singleton
* _ This class is itself a simple implementation Singleton
* (either recursive or simply "joking").
* _ The Singleton really is not a Singleton but a possible Singleton
* The transfert to more than one instance of the class is almost
* straight forward.
*
* @author <a href="mailto:tsmets@altern.org">Thomas SMETS, Brussels</a>
* @version 0.0.1 initial
*/
public class SingletonFactory
{
public static final SingletonFactory instance = new SingletonFactory ();
public static final int INITIAL_SIZE = 5;
public static Singleton[] refs = new Singleton[INITIAL_SIZE];
private SingletonFactory ()
{
System.out.println ("private SingletonFactory ()");
}
public static SingletonFactory getInstance ()
{
System.out.println ("public static SingletonFactory getInstance ()");
return instance;
}
public Singleton getSingleton ()
{
synchronized (refs)
{
if (refs[0] == null)
{
refs[0] = new Singleton ();
return refs[0];
} else
return refs[0];
}
}
}
The Client is almost not changed : package test.lang.design_pattern.creational.singleton.withFactory;
/**
* Client:
* @author ben@javacoder.net
* @date January 2002
*/
public class SingletonClient {
public static void main(String[] args)
{
// use getInstance to obtain Singleton instance
Singleton s = SingletonFactory.getInstance().getSingleton ();
// use operation
s.action ();
}
}
The great advantage of this is that the Factory is placed outside the class, itself... which make the code cleaner & just as efficient !
Hope this helps,
Tx to J. B. Rainsberger for his nice article.
Tx to Gino MARCKX to ahve forced us to use the Factories everywhere :-D
Thomas SMETS,
SCJP2 - Brussels