Singleton: How Should It Be Used

On design patterns: When should I use the singleton?

On my quest for the truth I discovered that there are actually very few "acceptable" reasons to use a Singleton.

One reason that tends to come up over and over again on the internets is that of a "logging" class (which you mentioned). In this case, a Singleton can be used instead of a single instance of a class because a logging class usually needs to be used over and over again ad nauseam by every class in a project. If every class uses this logging class, dependency injection becomes cumbersome.

Logging is a specific example of an "acceptable" Singleton because it doesn't affect the execution of your code. Disable logging, code execution remains the same. Enable it, same same. Misko puts it in the following way in Root Cause of Singletons, "The information here flows one way: From your application into the logger. Even though loggers are global state, since no information flows from loggers into your application, loggers are acceptable."

I'm sure there are other valid reasons as well. Alex Miller, in "Patterns I Hate", talks of service locators and client side UI's also being possibly "acceptable" choices.

Read more at Singleton I love you, but you're bringing me down.

Singleton: How should it be used

Answer:

Use a Singleton if:

  • You need to have one and only one object of a type in system

Do not use a Singleton if:

  • You want to save memory
  • You want to try something new
  • You want to show off how much you know
  • Because everyone else is doing it (See cargo cult programmer in wikipedia)
  • In user interface widgets
  • It is supposed to be a cache
  • In strings
  • In Sessions
  • I can go all day long

How to create the best singleton:

  • The smaller, the better. I am a minimalist
  • Make sure it is thread safe
  • Make sure it is never null
  • Make sure it is created only once
  • Lazy or system initialization? Up to your requirements
  • Sometimes the OS or the JVM creates singletons for you (e.g. in Java every class definition is a singleton)
  • Provide a destructor or somehow figure out how to dispose resources
  • Use little memory

When should I use Singleton pattern?

Yes, you misinterpreted the pattern.

You have 1:1 relationships (which seems correct), but designing e.g. the user as a singleton would mean that you could only have one customer in your shop.

The singleton pattern might make sense for the authentication service as you probably want one single instance to answer if a given user has a valid session (in contrast to having multiple service instances where the user might have to log in to every single one).

In what circumstances should I use a Singleton class?

I've found that the singleton pattern is appropriate for a class that:

  • Has no state
  • Is full of basic "Service Members"
  • Has to tightly control its resources.

An example of this would be a data access class.

You would have methods that take in parameters, and return say, a DataReader, but you don't manipulate the state of the reader in the singleton, You just get it, and return it.

At the same time, you can take logic that could be spread among your project (for data access) and integrate it into a single class that manages its resources (database connections) properly, regardless of who is calling it.

All that said, Singleton was invented prior to the .NET concept of fully static classes, so I am on the fence on if you should go one way or or the other. In fact, that is an excellent question to ask.

When should the Singleton pattern NOT be used? (Besides the obvious)

Summary Version:

You know how often you use globals? Ok, now use Singletons EVEN LESS. Much less in fact. Almost never. They share all the problems globals have with hidden coupling (directly impacting testability and maintainability), and often the "only one can exist" restriction is actually a mistaken assumption.

Detailed Answer:

The most important thing to realize about a singleton is that it is global state. It is a pattern for exposing a single instance of globally unmitigated access. This has all of the problems in programming which globals have, but also adopts some interesting new implementation details and otherwise very little real value (or, indeed, it may come at an unnecessary extra cost with the single instance aspect). The implementation is different enough that people often mistake it for an object oriented encapsulation method when it is really just a fancy single instance global.

The only situation in which you should consider a singleton is when having more than one instance of already global data would actually be a logical or hardware access error. Even then you should typically not deal with the singleton directly, but instead provide a wrapper interface which is allowed to be instantiated as many times as you need it to be, but only accesses global state. In this manner you can continue to use dependency injection and if you can ever unmarry global state from the behavior of the class it isn't a sweeping change across your system.

There are subtle issues with this, however, when it appears as if you are not relying on global data, but you are. So that (using dependency injection of the interface which wraps the singleton) is only a suggestion and not a rule. In general it is still better because at least you can see that the class relies upon the singleton whereas just using the ::instance() function inside the belly of a class member function hides that dependency. It also allows you to extract classes relying on the global state and make better unit tests for them, and you can pass in mock do-nothing objects where if you bake reliance on the singleton directly into the class this is MUCH more difficult.

When baking a singleton ::instance call which also instantiates itself into a class you make inheritance impossible. Work-arounds typically break the "single instance" part of a singleton. Consider a situation where you have multiple projects relying on shared code in a NetworkManager class. Even if you want this NetworkManager to be global state, and single instance, you should be very skeptical about making it into a singleton. By creating a simple singleton which instantiates itself you are basically making it impossible for any other project to derive from that class.

Many consider the ServiceLocator to be an anti-pattern, however I believe it is a half step better than the Singleton and effectively eclipses the purpose of the Go4 pattern. There are many ways to implement a service locator, but the basic concept is that you break up the construction of the object and the access of the object into two steps. In this way, at runtime, you can connect the appropriate derived service, and then access it from a single global point of contact. This has the benefit of an explicit object construction order, and also allows you to derive from your base object. This is still bad for most of the stated reasons, but it is less bad than the Singleton and is a drop-in replacement.

One specific example of an acceptable singleton(read: servicelocator) may be in wrapping a single-instance c style interface like SDL_mixer. One example of a singleton often naively implemented where it probably shouldn't be is in a logging class (what happens when you want to log to console AND to disk? Or if you want to log subsystems separately.)

The most important problems of relying on global state, however, pretty much always come up when you're trying to implement proper unit testing (and you should be trying to do that). It becomes so much harder to deal with your application when the bowels of classes that you don't really have access to are trying to do unmitigated disk writing and reading, connect to live servers and send real data, or blast sound out of your speakers willy nilly. It's much, MUCH, better to use dependency injection so you can mock up a do-nothing class (and see that you need to do that in the class constructor) in case of a test plan and point it at that without having to divine all the global state your class depends on.

Related Links:

  • Brittleness invoked by Global State and Singletons
  • Dependency Injection to Avoid Singletons
  • Factories and Singletons

Pattern Use vs Emergence

Patterns are useful as ideas and terms, but unfortunately people seem to feel the need to "use" a pattern when really patterns are implemented as need dictates. Often the singleton specifically is shoehorned in simply because it's a commonly discussed pattern. Design your system with an awareness of patterns, but do not design your system specifically to bend to them just because they exist. They are useful conceptual tools, but just as you don't use every tool in the toolbox just because you can, you shouldn't do the same with patterns. Use them as needed and no more or less.

Example Single-Instance Service Locator

#include <iostream>
#include <assert.h>

class Service {
public:
static Service* Instance(){
return _instance;
}
static Service* Connect(){
assert(_instance == nullptr);
_instance = new Service();
}
virtual ~Service(){}

int GetData() const{
return i;
}
protected:
Service(){}
static Service* _instance;
int i = 0;
};

class ServiceDerived : public Service {
public:
static ServiceDerived* Instance(){
return dynamic_cast<ServiceDerived*>(_instance);
}
static ServiceDerived* Connect(){
assert(_instance == nullptr);
_instance = new ServiceDerived();
}
protected:
ServiceDerived(){i = 10;}
};

Service* Service::_instance = nullptr;

int main() {
//Swap which is Connected to test it out.
Service::Connect();
//ServiceDerived::Connect();
std::cout << Service::Instance()->GetData() << "\n" << ((ServiceDerived::Instance())? ServiceDerived::Instance()->GetData() :-1);
return 0;
}

When should I use a singleton class in C++?

The only time you should use a singleton is in the rare case where it is VITAL that there only ever be one of these objects. This simply doesn't come up nearly as often as you might think.

Quite often it's more than sufficient to just make a single instance of the class in question, but not put in all the machinery required to enforce the uniqueness of the object.

Every time I've used a singleton (or found one in the codebase I work with) I've ended up removing it because I needed to change the behavior, and the singleton machinery got in the way. I've yet to see a case in our code (payment processing) where a singleton actually made sense. I've got more than a few cases where I've only got one instance of a particular class, but none where enforcing that through the singleton pattern was necessary or helpful.

What is singleton pattern?Why and When should I use it? [duplicate]

Singleton pattern gives you the control over the number of instances of the singleton class that can be instantiated. It is used numerous use cases.

The classic Java singleton looks just as you mentioned with a very important detail - the non public constructor.

The fact that the constructor is not public (either protected or private) will not allow anyone to create a new instance of singleton as you suggested:

Singleton singleton = new Singleton();

And that's the big difference than having just a regular class.

Note that such an implementation is not thread safe, and therefore you will either want to have it thread safe or non lazy initialized as follows:

  • Non lazy initialization

    public class Singleton {
    private static Singleton instance = new Singleton();

    private Singleton(){
    }

    public static Singleton getInstance(){
    return instance;
    }
    }
  • Thread safe

    public class Singleton {
    private static Singleton instance = null;

    protected Singleton() {
    }

    public static Singleton getInstance() {
    if (instance == null) {
    synchronized (Singleton.class) {
    if (instance == null) {
    instance = new Singleton();
    }
    }
    }
    return instance;
    }
    }

When should you use the singleton pattern instead of a static class?

  • Singletons can implement interfaces and inherit from other classes.
  • Singletons can be lazy loaded. Only when it is actually needed. That's very handy if the initialisation includes expensive resource loading or database connections.
  • Singletons offer an actual object.
  • Singletons can be extended into a factory. The object management behind the scenes is abstract so it's better maintainable and results in better code.


Related Topics



Leave a reply



Submit