开发者

What are some specific legitimate uses for singletons? [duplicate]

This question already has answers here: 开发者_高级运维 Closed 12 years ago.

Possible Duplicate:

On Design Patterns: When to use the Singleton?

This question is not about whether or not singletons are "considered harmful" in general. I just want to know, from your experience, what are some SPECIFIC SITUATIONS in which singletons seem to work well.

EDIT: Please, if you want to discuss the appropriateness and/or evilness of singletons in general, there are aleady exising questions: 137975, 11831

Oops! I've just discovered that my question has already been asked here: On Design Patterns: When to use the Singleton?


We basically use them for two things: logging, and configuration. Both assume that the app has a central config and a central logfile, not always valid but in most of our code it is. We also use them on occasion for certain factory classes or cache classes we want to make sure we're not duplicating key metadata.


Expanding my comment...

The question is poorly worded, singletons seem to work well in many situations. It should be "what are some specific situations in which singletons don't expose their negative properties?" Briefly, "when are global variables good"?

  1. A global variable is a global variable.

    As soon as you use

    void f() { X* x = X::getInstance(); ... }

    instead of void f(X*), your order for the spaghetti dish has been accepted.

  2. Singletons proliferate, and like to depend on each other. SessionManager uses EventManager which uses LogManager. Someone wants the log files to mention the name of the current user. The LogManager maintainer adds SessionManager::getInstance()->getUser()->getName();, everything's roses until the LoginManager, which also uses LogManager, wants to log a login failure.

  3. Singletons inhibit testability.

    The single-instance property is semi-useful only in production code. You may be unable to test the void f() function at all, and probably will have (few) tests only for the happy path.

As you can guess, my answer to when are global variables good? is "never". What is yours?


Generating a sequence of random numbers - the random generator should be unique, not instantiated for each use. One might want to implement this as a thread-level singleton; however, a singleton for the whole process is still appropriate in this case.


  • When your domain specifies that there only exists one unique instance of something you're modelling

I still believe singletons should be avoided (in Java at least).

There's two different things to consider: the concept and the mechanism for enforcing the Singleton pattern.

The concept of Singletons have many uses, logging, configuration, not to mention when the domain you're working actually has things where there is ever only one instance of them and you wish to model that. I.e. a company only has a single expenses processing office and sending expense forms to an invalid office is wrong, the office is in reality a singleton. The concept of a singleton has many legitimate uses.

However, it's usually the mechanism that causes the problem. In Java we enforce an object can't be constructed by declaring the constructor private, the problem with this is we also have to provide a global point of access to the instance through the concrete class. This couples everything in your application to that concrete class, which can't be changed at run-time, or mocked in unit testing. It's this mechanism which is considered evil - particularly in terms of testability.

If the concept of Singletons can be separated from the poor mechanisms, they would not be so evil. One example, I can think of is the @Singleton scope available in Guice. In the context of Guice, it guarantees one instance, but it doesn't achieve this with the evil private constructor/global point of access mechanism.


There is a single device/hardware attached to the system and a central point of control is necessary in order to use it properly.


  • Logging.

  • Finding localized string resources e.g. Strings.get("CONFIRM_DELETE").

Both of these things are not details that should be exposed in the public interface of your objects, so it makes sense to use a singleton here.


I just worked really hard getting rid of Singletons in the current project I am working on. They have a smell, but sometimes are very difficult to avoid.

My situation was that I had an API which constructed singleton objects for handling management functions such as Security, Configuration, etc. The API used EntityFramework and also pulled in PlugIns (using MEF). Because the construction of these classes was not always performed by my code (particularly for EF entities), it was not always possible to inject these into biz objects elegantly. So I used singletons, which can be accessed anywhere within a project subject tot heir scope.


Master server takes requests from clients, and passes these requests off to a subordinate process. The subordinate process may use a singleton for communicating with the master server.


I try not to rely on Singleton, however I prefer decoupling to not using Singleton. Thus, I often use Singleton coupled with the Prototype pattern, which allow for registering the Prototypes at library load (global objects construction).

I am writing a server consisting of a number of libraries. There is a number of "common" libraries, then one library per service. A "main" library is tasked with the purpose of looking at the message received and invoked the right service depending on a key... This uses a simple std::map.

Using a Singleton for the map allow me to have totally decoupled code. No library depends on my service library, no line of code outside my service library is tasked with registering its service. In fact, it is such that I can decide which services are embedded simply by altering my "link" command at compile-time: if I do not link with a library, its service is not embedded.

I really find it useful there... for configuration and such I prefer to use the MonoPattern: ie normal looking class with all instances sharing the same data (thus wrapping a real singleton). Makes for easier migration just in case it's necesary since the clients don't know they are using a Singleton undercover.


In addition to logging (as most others have already mentioned), I've used singletons for Inversion of Control (IoC) Containers. The dependencies are registered once at the start of the application, and one can resolve a dependency at any point in time during the app using the singleton method.


They're good for items that you wish to consider as unique resources.

As an example in web systems you may wish to only use a single database connection for each page that's served - in this instance using the singleton pattern would make sense. (Although you'd have to code with the knowledge that the database access object was a singleton, which is less ideal, but acceptable if clearly documented, etc.)


When a part of your program needs an object that implements a specific interface (polymorphism-wise), but you never want more than a single instance of that object. Otherwise static methods will do.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜