The only difference is whether the state of the CreditCardProcessor is stored statically on the class, or is stored in one magical instance. They will both have the exact same pathology in the code and during testing. The former will be slightly easier to refactor, since at least it's already based on instances.
But the whole point of the singleton pattern is to solve these exact issues. To enforce a single entry point that is 1. Lazy evaluated to ensure initialization.
2. Preferably locked to solve threaded access.
3. Instance based to ensure you are manipulating an object vs truly static variables.
I honestly think there's a huge potential difference between
Solve what issues? I did not mention any issues. I see no difference between the two, other than one basically enforces initialization by gating it through a "getInstance" call. (And thereby also enforcing an additional function-call penalty on every functionality presented. Nothing is free.) I could do the same, with the same trade-offs, by simply invoking init() at the start of every method call.
To address your points specifically:
1. Whether the item is lazily initialized or not is an implementation detail. In fact, the call of "init" on the first format is lazy initialization; an eager initialization would have completed at class-load.
2. Either method can implement exclusionary locks. There is no difference here.
3. This is the big difference between the two, but you write it as if it's a benefit unto itself. From an API perspective, why do I care whether I'm manipulating an variables that live on an object instance or statically on the class?
Here's an exercise. How would you even know whether the code to a Singleton class looks like this?
class SomeNumber {
private static Integer value;
public static SomeNumber getInstance() {
if (value == null) value = 5;
return new SomeNumber();
}
public Integer getValue() {
return value;
}
}
If you cannot tell whether the Singleton class was implemented this way from the external API, then there is no difference between the two implementations.
Invoking init at the start of every method call won't be caught by the compiler if you forget to do it in one spot. Static safety is usually a win - on a big project, someone will do something wrong and it's best if it's caught right away when they try to compile.
I've actually been wanting ways of enforcing arbitrary rules on the structure of my code at compile time...