26

This question already has an answer here:

I've searched about this here and on StackOverflow and found some differences between the two.

But I'm still not sure in what cases one would prefer a Singleton, and in what cases one would choose to use a static class.

(In languages which don't support 'static classes', like Java, I'm obviously referring to classes containing only static methods and fields).

Please give me concrete examples of cases where you would pick each one, and explain why.

marked as duplicate by gnat, Michael Kohne, Konrad Morawski, Caleb, BЈовић Apr 10 '14 at 15:01

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

29

A case where a static class might be a good idea is when you want to collect related pieces of functionality, but you don't need to have any internal state in any object. An example could be the Math class in Java. It contains a whole bunch of related functions that are accessed outside the context of any specific object instance. I've done similar things where a set of common utility functions that are used in multiple places in an application are grouped together into a single utility class.

A singleton is used when you do want an actual object (with its own internal state and everything), and you want to limit your system to exactly one instance of that object. This might be useful if you have some kind of shared resource, such as a database, an in-memory cache, or maybe some specialized piece of hardware like a robotic arm. Many parts of your program might want to use this resource and you might want to have all access to the resource go through a single point. A singleton isn't always the only way to handle these situations, but it's one of the few places I think a singleton might be a good choice.

  • 2
    If so, question: A static class can also have internal state that can be manipulated and used, just like an object, right? – Aviv Cohn Apr 10 '14 at 13:56
  • 4
    @Prog Because you're just using global variables in disguise. All parts of your application that make any calls to the static class are now invisibly dependent on each other, and any parts of your application that are dependent on those parts are now indirectly dependent as well, and so on. Mutable state is already a bad idea if you can avoid it. Global mutable state is just a bad idea. – Doval Apr 10 '14 at 14:05
  • 1
    @Prog - that's a different question ("Why should a static class have no state?"). Please ask it separately, not in the comments here. – Scott Whitlock Apr 10 '14 at 14:05
  • 2
    @Prog just because there's only one database it doesn't mean you want to enwrap database access in a singleton, for example because you can't mock a singleton and thus inject a "dummy" database into a unit test, for example. Okay, you CAN mock a singleton, but this can require a bit of voodoo (depending on your language of choice) and isn't very convenient. – Konrad Morawski Apr 10 '14 at 14:11
  • 2
    @Prog As pointed out by Scott, you should ask a new question for that one. We've strayed too far off course from this one. – Doval Apr 10 '14 at 14:14
9
  • Avoid the Gang of Four Singleton pattern, for reasons cited in the other answers. Mainly it is an anti-pattern based on difficulties it creates for testing.

  • Factory and Dependency Injection made Singleton obsolete. The best answer is to use a Factory that decides whether to instantiate one instance, or many, of a given class. That way, the class and its clients aren't responsible for its singleton status -- that becomes a transparent concern managed by the Factory.

  • Dependency injection frameworks like Spring do that for you out of the box (e.g. Spring beans are singletons unless you specify otherwise).

  • Purely static classes are problematic for both testing and using OO concepts. I've seen teams with an irresistible urge to make everything static and final, and the question becomes, why aren't they just writing C code?

  • If your static class has side effects, then it should not be static. That means, if it's managing shared state, or if it's changing the state of parameters, then it should be a regular class where the Factory hands out a single shared instance. A purely static class that manages shared state becomes a really hard problem for testing.

  • A purely static class also creates hard, compile-time dependencies on that particular class, which really compromises the extend-ability and test-ability of your code. Seems like you'd want to reserve that for something eternal and unchanging, with no side effects, like math formulas.

So the answer is, don't write classes as singletons, but rather move that decision into your Factory. And in an OO language, static classes miss some of the most important design aspects of the language and complicate testing. Again, you can use worker classes with specific semantics to bundle those up and have them generated by your Factory.

  • 3
    +1 for your second bullet point. Factories can be a good abstraction of object construction, to include caching instances when appropriate. It also adds flexibility to change the instance if needed, e.g. for injecting a mock test class. – user22815 Apr 10 '14 at 14:50
  • Thanks for answering. Thing is, in order for me to be able to create instances of that class from anywhere in the program, I need the Factory to be global. Calls for a Singleton..? – Aviv Cohn Apr 10 '14 at 22:36
  • If you have to do something bad, then concentrating it in one place is a good mitigating factor. ;) But in this case, there are a couple of strategies you can use: 1) have your application framework inject a common type-specific factory into your classes, 2) use the Prototype pattern, in which an instance of an object turns into a kind of factory from which other instances are cloned. Essentially, you already have a global context -- the running application -- and that's what should be responsible for building & handing things out. – Rob Apr 10 '14 at 23:58
0

Singletons objects made so there can only be 1 instance at any given time and can be used application wide.

Objects that handle stuff like connection pools are a good candidate to be Singletons;

  • You only want 1 instance in the entire application
  • you must be able to access it from different parts of the application
  • the data it holds has to be persisted even when no other objects are currently pointing to it (handy when you want to reuse objects that are expensive to initialize).

A class filled with only static methods is not something that's usually meant to be initialized like an object. It's more like a wrapper for the static methods in it.

An example of this that I use frequently is a utility class with methods that do repetitive tasks that take parameters, does a calculation with them/formats them/etc. and then returns the result, without using any external (or at least no non-static) fields or methods. I never initialize a utility class, I just use the static methods in it for all repetitive methods.

This is just how I tend to use Singletons and static (method filled) classes, not sure if it confirms to any "official" standards...

  • FrustratedWithFormsDesig already gave a better answer in the time I took to type my answer... – Rob Apr 10 '14 at 13:58
  • Thanks for your answer. If you have an entity that needs to be accessible from anywhere in your application and only one instance of it at a time, like a database, why not implement it as a static class? Static classes can also hold internal state and have public methods to access and manipulate it. Why not simply implement a static class? – Aviv Cohn Apr 10 '14 at 14:04
  • For me personaly it's the convenience of only having to make the instance object and getInstance() method static. This avoids a lot of "can't call non-static method" kind of errors. Other than that I can't really come up with a valid reason. – Rob Apr 10 '14 at 14:15
  • I was confused for a moment why Rob gave two answers, but then I realized – asgs May 14 '17 at 21:24

Not the answer you're looking for? Browse other questions tagged or ask your own question.