I saw this while using picocontainer. They say you have to avoid singletons. because the Singleton pattern makes it almost impossible for the class (and possibly all other classes which depend on it) to be testable. It's very hard to subclass, or to create a mock object for a Singleton class.
But if you absolutely need it , Is there a workaround for the testing and subclassing issue ?
A singleton class has a private constructor which is not accessible to any other class inside the same package or outside. Hence it cannot be sub classed from any other class.
The Singleton pattern is a useful pattern in Android development, and Java development at large. The Singleton pattern is defined as follows: In software engineering, the singleton pattern is a design pattern that restricts the instantiation of a class to one object.
Subclassing a Singleton class may be tricky, since a subclass object cannot be created unless the superclass object has not yet been created. You may want to extend the Singleton class to allow not just a single instance, but some small fixed maximum number of instances.
Singleton object is pretty hard to fake in tests and thus we can consider it as untestable code. Singleton keeps state for the lifetime of the application. So we cannot run several tests using this object at the same time, they will conflict with each other.
What makes it hard to test singletons is the code enforcing their singleton-ness (meaning the public static MySingleton getInstance() {...}
boilerplate). Using an inversion-of-control container, like Picocontainer or Guice or Spring, removes that concern from the object, so now:
It can be instantiated and have collaborators plugged into it in tests without a problem.
The code calling a singleton doesn't have to know what class it is looking up (which it would need to know if it had to call a static method).
I interpret the advice on picocontainer's website as being similar to this. What they are telling you is, let our container manage the scope of your components for you, don't hard-wire the scope-enforcing code into them.
If you must have singletons:
Example:
interface IBankApi
{
public void MakeDeposity(int accountNumber, int dollarAmount);
// ...
}
public class RealBankApi : IBankApi { ... }
// startup code
serviceLocator.Register<IBankApi>(new RealBankApi());
// code using the API
serviceLocator.Resolve<IBankApi>().MakeDeposit(...);
// test code setup
class FakeBankApi : IBankApi { ... }
serviceLocator.Register<IBankApi>(new FakeBankApi());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With