Skip to content

Instantly share code, notes, and snippets.

@dhoechst
Last active December 23, 2015 12:39
Show Gist options
  • Save dhoechst/6636852 to your computer and use it in GitHub Desktop.
Save dhoechst/6636852 to your computer and use it in GitHub Desktop.
Trying to understand the singleton pattern and why some people consider it bad.
// from http://wiki.developerforce.com/page/Apex_Design_Patterns_-_Singleton
// What makes this a singleton pattern? Is it that it uses a private constructor?
public class AccountFooRecordType {
// private static variable referencing the class
private static AccountFooRecordType instance = null;
public String id {get;private set;} // the id of the record type
// The constructor is private and initializes the id of the record type
private AccountFooRecordType(){
id = Account.sObjectType.getDescribe()
.getRecordTypeInfosByName().get('Foo').getRecordTypeId();
}
// a static method that returns the instance of the record type
public static AccountFooRecordType getInstance(){
// lazy load the record type - only initialize if it doesn't already exist
if(instance == null) instance = new AccountFooRecordType();
return instance;
}
}
// My attempt at making it better.
// Instead of having a private constructor I just return the private variable after checking if it is null or not
public class AccountFooRecordType {
private static Id instance;
public static Id getInstance() {
if (instance == null) instance = Account.sObjectType.getDescribe()
.getRecordTypeInfosByName().get('Foo').getRecordTypeId();
return instance;
}
}
@pcon
Copy link

pcon commented Sep 20, 2013

What makes this a singleton is line 17 of the first one. If it is null (ie not been accessed) then we set it up. If it has been accessed, then we give the instance we already have. Thus reducing the number of "backend" calls

@dhoechst
Copy link
Author

So wouldn't the second one also be a singleton too, then? Line 8 also checks to see if it has been accessed and lazy loads.

@britishboyindc
Copy link

The second one is the easiest approach. But the second one is NOT a singleton pattern I believe, because no instance of the class is evert instantiated - you are calling a method on the class itself, not an instance of the class. Take a look at the Java docs for some more detailed explanation: http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html

Because all objects in SF only persist for the length of the transaction (e.g. a trigger execution), you don't get any benefit from the singleton pattern as far as I know. Next time the trigger fires, you are going to have to instantiate again - so you might as well just call a static method to achieve the same thing. Where it makes sense is the example Matt referred to in his SE post - you are running a program with a framework that persists state, and a class should have one instance of a class running, but only ever one...

@dhoechst
Copy link
Author

Thanks! That's what I was thinking too. After some more reading this morning and watching the DF session on Apex patterns, I think I understand the difference. I actually am using the approach in the second one. One of my coworkers called it a singleton and that threw me off. What I really learned from all this is that static can actually persist through the entire transaction. I had always assumed you had to instantiate an object to get persistence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment