Singletons: Pros,Cons, Design Concerns [closed]
I admit it. I am using singletons. I know what you may all say, and frankly, seeing all these answers on the Internet, saying about the bad aspects of singletons, and advising against them really made me question my programming practices.
I have already read some posts in StackOverflow regarding Singletons, but I post this question not only to ask about them, but to see some insights about the way I use them in my programs.
I feel I must really clarify some things here and ask fore directions.
So lets consider some cases where I use singletons a lot:
- To c开发者_如何学Goreate accessors to global variables, like my root view controller, specific and always existing view controllers, application state, my global managed object context... stuff like that
- To create utility classes whose job is to handle data application-wide. For example, I create a Singleton that will operate my caching database, which relies on Core Data. Since I need to create caches and other stuff to be put in the database in different views, it somehow felt better to create a class that will handle database ins/outs (being careful about thread safety).
- Handling network sessions. Actually, I use it to keep alive a connection and sending something like a PINg to a server each XX seconds.
I think that about sums it up. I would really like opinions from other developers on the matter.
Do you think that there are better solutions for these problems above?
Do you think that there are always better alternatives to singletons and that they should be avoided?
Is it better in terms of multithreading to forget about singletons?
Any recommendations and thoughts would be useful, and most welcome.
Singletons are certainly not always evil, but as you mention you have to be careful about thread safety (on that topic, check out this blog post on singleton initialization).
One reason why singletons are often decried as evil is that they can make it harder to "scale" parts of a program if they rely too much on a singleton and its behavior. You mention database access, a server or desktop application might start out with singleton implementation to handle all database needs and then later try to use multiple connections to speed up independent requests, etc. Breaking up such code can be very hard.
Even in an iOS application using CoreData it can be useful to not rely on a global ManagedObjectContext on your application delegate or some root view controller.
If you pass each view controller a reference to a ManagedObjectContext you can gain some flexibility. Most of the time you'll just pass the same context from one view controller to the next, but if you ever decide to in the future, you can for example create a new ManagedObjectContext for an editing view where you can use the undo features of the context but only merge the changes back into the "root" context if the user decides to save them or easily discard them otherwise. Or maybe you want to do some background processing on a whole set of objects. If everything operates on the same context, you'll end up with synchronization issues.
- To create accessors to global variables, like my root view controller, specific and always existing view controllers, application state, my global managed object context... stuff like that
Singletons are globals. Wrapping a global with another global doesn't really help anything.
- To create utility classes whose job is to handle data application-wide. For example, I create a Singleton that will operate my caching database, which relies on Core Data. Since I need to create caches and other stuff to be put in the database in different views, it somehow felt better to create a class that will handle database ins/outs (being careful about thread safety).
Sure, but this probably doesn't need to be a singleton. Indeed, part of the design of Core Data is that it is valid to have multiple MOCs that talk to the same store.
- Handling network sessions. Actually, I use it to keep alive a connection and sending something like a PINg to a server each XX seconds.
This should be a singleton if the server might enforce some n-connections-per-user/IP-address limit. Otherwise, it probably does not need to be a singleton.
As I mention in my aforelinked blog post, the solution I prefer is to have each object own each other object. For example, your MOC and connection objects would each be owned by any object(s) that need to work with them. This improves memory and resource management (singleton objects never die) and makes the overall design of the application that much more straightforward.
精彩评论