In a recent post, someone asked about implementing the Singleton Pattern in Apex, and I offered this link as a resource, and there was also this session at DF 11 that talked about the Singleton pattern. @kraybill suggested that a stateful singleton in Apex didn't really exist/make sense, but that made me wonder whether using it for a non-stateful purpose is also an overkill. The DF 11 session explains how you could use it for as a RecordType Lookup Cache Utility to avoid multiple describes - and I have such a need for a trigger handler class I am building. But I know I could also just add a couple of static map variables to a class, and a getter that populates the map if it is null, which would achieve the same thing. So are there are pros-cons to either approach? If the Singleton pattern is not appropriate here, is there a time when it is? Any insights appreciated!
Singletons not only are not needed in Apex, they are basically pointless. In that previous thread, I described why stateful singletons are pointless, but stateless singletons are pretty much in the same boat, simply because the instantiation/cache step is unnecessary.
In Apex, I've found that abstract utility classes with all-static methods are the equivalent of a Java/Spring service layer (without dependency injection). In practice they behave the same as a stateless singleton class anyway. We have dozens of these in our app, which are used to do anything servicey, such as the describe call caching you mentioned.
When you're in an environment that is born and dies within the scope of a single (single-threaded) request, the singleton pattern is irrelevant. Static achieves the same ends, including state sharing within the request if that's what you need.
In my opinion
static is all you really need when working in this environment due to the fact that code runs in a new context each time the user performs an action.
I've used singletons a lot when writing games, typically I'll have a single instance of a class called SoundManager, one called InputManager, and a bunch of others that are responsible for managing particular interfaces and resources. In this context you wouldn't want to have more than one instance to keep memory usage at a minimum, but you may not want to flexibility to destroy objects when they're not needed.
For example, a front-end menu manager would likely not be needed in-game, so it's prudent to delete it and free up the memory it's using. When you're back in the front end you can create a new singleton instance and wouldn't want to have more than instance trying to manage the display.
Maybe I am going about it wrong but this pattern has become extremely useful in a service class used across multiple classes/methods both within the current namespace and from extension namespaces.
The service class sets multiple values based on dynamic apex and org shape that if executed each time would decrease performance and potentially cause collision based on the entry point.
Especially when the order of operations is critical or when specifying initialization properties that could differ depending on the entry point.
Just thought I would add my 0.0000001 cents to the discussion
I am not comfortable with static. And the top voted answer is miss-leading. Whenever there is a static class, there should be a singleton service class, so during unit test it is possible to be replaced with a mockup service. Here are some other differences citied from another Singleton vs Static thread:
“The big difference between a singleton and a bunch of static methods is that singletons can implement interfaces (or derive from useful base classes, although that’s less common, in my experience), so you can pass around the singleton as if it were “just another” implementation.”
A singleton allows access to a single created instance - that instance (or rather, a reference to that instance) can be passed as a parameter to other methods, and treated as a normal object. A static class allows only static methods.
Here is an Apex DI framework you can use to easily register singleton services:
DI.IServiceProvider provider = new DI.ServiceCollection() .addSingleton(UISettingCacheService.class) .addSingleton(ProductCategoryCacheService.class) .addTransient(IAccountService.class, AccountService.class) .buildServiceProvider();