Read more at, or return to the homepage

Building A Better Singleton

In the last post on Picklist Validation, I touched briefly on my disappointment in being unable to bring to fruition a better pattern for creating singletons — the perfect way to access constant values like those in a picklist:

I hate writing singleton property accessors, and have spent more hours than I'd care to admit trying to "solve" that problem through a variety of abstract class hacks ... none of which has borne any fruit. That's the nature of progression, though — failure is a part of the process.

In the ensuing weeks, I spent a considerable portion of time simply spent bulleting out thoughts about the "problem" that I had first introduced in the Idiomatic Apex post:

Last night, while winding down, the situation finally resolved itself in a burst of inspiration. Messily implemented first in my notebook (my handwritten braces get progressively worse), I finally figured out how to resolve the static nature of singletons with an object-oriented approach:

1linkpublic abstract class Singleton {

2link private static final Map<Type, Singleton> typeToSingleton

3link = new Map<Type, Singleton>();


5link public static Singleton getSingleton(Type type) {

6link if(typeToSingleton.containsKey(type) == false) {

7link typeToSingleton.put(type, (Singleton)type.newInstance());

8link }

9link return typeToSingleton.get(type);

10link }


Going back to the Picklist class from the previous post, now the base class just needed to extend Singleton so that subclasses could make use of the type:

1linkpublic abstract class Picklist extends Singleton {

2link //...etc



5linkpublic class AccountIndustries extends Picklist {

6link public AccountIndustries() {

7link super(Account.Industry);

8link }


10link //the newer invocation

11link //note that because there isn't a "set"

12link //method, if I wasn't going for mobile

13link //friendly code, this could be reduced to a single line

14link public static AccountIndustries Current {

15link get {

16link return (AccountIndustries)Singleton.getSingleton(AccountIndustries.class);

17link }

18link }


20link //the more idiomatic singleton, for testing purposes

21link public static AccountIndustries Instance {

22link get {

23link if(Instance == null) {

24link Instance = new AccountIndustries();

25link }

26link return Instance;

27link }

28link private set;

29link }


31link public String AGRICULTURE { get { return this.getValue('Agriculture'); }}

32link public String APPAREL { get { return this.getValue('Apparel'); }}


Of course, it's not enough to simply have code that compiles — is it performant? Let's do some simple iteration to stress test this new Singleton pattern:


2linkprivate class SingletonStressTests {

3link @isTest

4link static void it_should_establish_a_baseline_iteration_time() {

5link runTest(null);

6link }


8link @isTest

9link static void it_should_use_idiomatic_singleton() {

10link runTest(new TestIdiomaticSingleton());

11link }


13link @isTest

14link static void it_should_use_new_singleton() {

15link runTest(new TestNewSingleton());

16link }


18link static void runTest(TestFunction function) {

19link for(Integer index = 0; index < 10000; index++) {

20link if(function != null) {


22link }

23link }

24link }


26link private abstract class TestFunction {

27link public abstract void call();

28link }


30link private class TestIdiomaticSingleton extends TestFunction {

31link public override void call() {

32link System.debug(AccountIndustries.Instance.AGRICULTURE);

33link }

34link }


36link private class TestNewSingleton extends TestFunction {

37link public override void call() {

38link System.debug(AccountIndustries.Current.AGRICULTURE);

39link }

40link }


Woof. Initial results were not promising:


At first, I wondered if perhaps the dynamic Type.newInstance, or perhaps even the usage of the internal Map within the Singleton class was responsible for the slowdown. I would expect that there would be some slowdown, some overhead, in the usage of this more complicated setup ... however, I did not expect that the new method would be six times slower. Of course, in actual usage, such slowdown might not matter for your application ... but that's not the Joys Of Apex way. While I was ecstatic at the notion of saving 8 lines of code through the use of this new singleton one-liner, I wasn't about to recommend that to my clients if it meant taking such a big performance hit.

I tried eliminating the map. I tried passing an actual instance of the class to the getSingleton function (in this case, using new AccountIndustries) instead of dynamically spinning an instance up. Nothing. No changes reduced the runtime appreciably.

Then it hit me — the property Current itself was not being cached. Just for kicks, let's switch to the more idiomatic method for instantiating singletons to see if that made up any ground in terms of performance:

1linkpublic static AccountIndustries Current {

2link get {

3link if(Current == null) {

4link Current = (AccountIndustries)Singleton.getSingleton(AccountIndustries.class);

5link }

6link return Current;

7link }

8link private set;


The results were fascinating:


OK, so the pattern was not itself responsible for the performance slowdown. That was great news. It wasn't great news that it still took 9 lines of code to retrieve a singleton instance. Apex does feature static constructors, but those are no good; was there any way to ensure that the property was only initialized once without all the boilerplate?

Perhaps you see where this is headed now. There is, of course, one last trick up our sleeves — the final keyword. Traditionally used to ensure an object's dependencies are set only in the constructor, final is also compatible with static variables and ensures that they are only ever initialized once.

That makes the AccountIndustries object look pretty svelte indeed:

1linkpublic class AccountIndustries extends Picklist {

2link public AccountIndustries() {

3link super(Account.Industry);

4link }


6link public static final AccountIndustries Current = (AccountIndustries)Singleton.getSingleton(AccountIndustries.class);


8link //only keeping this property now to re-run the tests

9link public static final AccountIndustries Instance = new AccountIndustries();


11link public String AGRICULTURE { get { return this.getValue('Agriculture'); }}

12link public String APPAREL { get { return this.getValue('Apparel'); }}

13link //etc, adding constants as is necessary to

14link //represent your picklists values in code

15link //with minimal usage of "magic" strings

16link //and the added benefit of intellisense


Running the tests again:


Easy peasy. I ran the tests dozens of times — for whatever reason, the newer method was always a few milliseconds faster than simply caching the instance. One can only surmise that there exists some fairly interesting tail-end optimizations in how the compiler assembles the Type.newInstance code which gives it a slight edge over the use of the new keyword.

linkSingleton Pattern Conclusion

Lessons learned in building a better singleton:

One thing that should be noted with the usage of Type.newInstance() — it requires the usage of a public zero-argument constructor. That shouldn't come as a surprise for those of you following along from the Factory post. It does however, fly in the face of the more classic singleton pattern (which makes the constructor private in order to force invocation through the public static variable). That's definitely something to consider when making your object design choices. The limitations of the Type class in Apex have frequently proven less-than-ideal in testing, as well, since it requires elevating test classes to public that shouldn't have to have elevated visibility. As always, food for thought.

I hope that this post proved educational for you. The usage of singletons is fairly common, and knowing that you have some tricks up your sleeve when you need to implement one is always a good thing. Till next time!

The original version of Building A Better Singleton can be read on my blog.

Singleton Pattern Conclusion

Home Advanced Logging Using Nebula Logger Apex Logging Service Apex Object-Oriented Basics Batchable And Queueable Apex Building A Better Singleton Continuous Integration With SFDX Dependency Injection & Factory Pattern Enum Apex Class Gotchas Extendable Apis Formula Date Issues Future Methods, Callouts & Callbacks Idiomatic Salesforce Apex Introduction & Testing Philosophy Lazy Iterators Lightweight Trigger Handler LWC Composable Modal LWC Composable Pagination LWC Custom Lead Path Mocking DML React Versus Lightning Web Components Refactoring Tips & Tricks Replacing DLRS With Custom Rollup Repository Pattern setTimeout & Implementing Delays Sorting And Performance In Apex Test Driven Development Example Testing Custom Permissions The Tao Of Apex Writing Performant Apex Tests

Read more tech articles