I'm sure many of you are familiar with the Singleton pattern. Simply put, it's a class that can only have a single instance, and the accessor for the instance is global.
Kristopher is certainly no stranger to the pattern, though he was thrown for a bit of a loop when he noticed this often-repeated pattern called Singleton in his new employer's codebase.
/* * Copyright: Copyright (c) 2008 * A 'service' that we can call to perform our enqueueing operations. * * Implementation is a singleton that holds the current data. */ public final class PublicationService { private static final Logger LOG = Logger.getLogger(PublicationService.class); private static final String[] CONTEXTFILES = new String[] { "applicationContext.xml" }; private static ClassPathXmlApplicationContext pubContext = null; public static PublicationService getInstance() { PublicationService instance = null; if (pubContext == null) { instance = new PublicationService(CONTEXTFILES); } else { instance = (PublicationService) pubContext.getBean("publicationService"); } return instance; } public PublicationService() { } protected PublicationService(final String[] contextFiles) { // try to load an application context Spring file, // it is okay if this fails try { final ClassPathXmlApplicationContext ctxt = new ClassPathXmlApplicationContext(contextFiles); ctxt.registerShutdownHook(); pubContext = ctxt; } catch (final Exception e) { LOG.info(" Unable to load ApplicationContext from " + contextFiles[0], e); } }
"So what's wrong?" Kristopher rhetorically asked, "for starters, the instance variable is not static and is created for every call to getInstance. Also, the constructor is public, allowing anyone to create a new instance (thus, not a singleton). Plus, that constructor (which creates an instance) grabs an instance of the same class out of Spring. And of course, by default, Spring makes all beans Singletons, so there's no need for this crap at all."
"The best part," Kristopher added, "the class says that it's a Singleton, but the first time you call getInstance, it has to create 2 instances."
Maybe this should be called a Doubleton. Or better... AtLeastTwoButNeverOne Pattern.