Hi Guys,
I'm confused recently over the implementation of the Singleton Pattern. In most of samples, the recommended implementation is:
public class MySingleton{ private static MySingleton instance; private Hashtable stuff; public MySingleton() { stuff = new Hashtable(); }
public static MySingleton CreateInstance { if(instance == null) instance = new MySingleton(); return instance; } public Hashtable GetStuff() { return stuff; }}
The usage will be:
MySingleton c = MySingleton.CreateInstance();Hashtable stuff = c.GetStuff();
However, is the following a singleton as well?
public class MyClass{ private Hashtable stuff; static MyClass { stuff = new Hashtable(); } public static Hashtable GetStuff() { return stuff; }}
Usage is:
Hashtable stuff = MyClass.GetStuff();
What do you guys think?
The melody of logic will always play out the truth. ~ Narumi Ayumu, Spiral
Depending on how pedantic you want to get, I found a number who strictly insist Singleton is numerically singular, and you term it Object Pool pattern should you want to control the existence of a limited number of objects of a certain class.
An interesting question and discussion of a variant order:http://discuss.fogcreek.com/joelonsoftware/default.asp?cmd=show&ixPost=165813
And an interesting note of singleton vs static.
Shunjie wrote:ajaxalinLogic n = new ajaxalinLogic();
This is a singleton on basis you indeed instantiate a live instance, instead of using a static instance; only the method call is static, which is different.
At first, everything pointed towards Singleton pattern being meaningless and not even deserving a name.
But I came across this definition, and I agree with it:
Singleton Pattern DefinitionThe Singleton pattern ensures that a class only has one instance and provides a global point of access to it from a well-known access point. The class implemented using this pattern is responsible for keeping track of its sole instance rather than relying on global variables to single instances of objects.http://www.devhood.com/tutorials/tutorial_details.aspx?tutorial_id=486
Now the question is, why/when use it?
As far as I see, one case is when the creation of the instance is not possible with a static initializer. (eg. the instance of the object may get destroyed at some point, or the instantiation requires parameters that may not be available at that time)
So if the instance never gets destroyed and can be created at a fixed point such as application startup, I don't see any benifit in using the Singleton pattern over normal static methods, unless you anticipate switching to Singleton pattern in future without changing your code.
hannes wrote:Now the question is, why/when use it?
Hane wrote
I strongly believe Singleton is a very good and useful pattern despite whatever voice oppostion has. The only thing I'm not clear is how it get destroyed when there is no more client holding an instance to it remotely. Do we have to implement the logic to free it from memory or the GC handles it for us?
From what I know, .Net Remoting provides the InitialLifetimeServices to control the life time of the object. Com object use reference counting and ping all clients to see if they respond to the call to determine the lifetime of the object. COM+ recycle it's objects at a certain interval and recreate them when required.
Yep Shunjie I agree with your second example, but in the example where the object is created once, it is just a preference (a valid one) not to use static methods. Syntactically it is the Singleton Pattern, but none of its uses are utilised. This is what actually confused me, because I could not see why anyone would call it a pattern.
Yep the reference count to the objects is an important part of this pattern. Multiple clients may be holding different instances of the class, although all but one (or none) of them are on their way to being destroyed as soon as the references are released. I have no idea how this works with remoting etc. though.
You may not agree, but I see this method as equivalent to a class implementing the Singleton pattern. (Proper locking is not implemented, but simultaneous access would be harmless.)
/// <summary> /// A cached list of measurements. /// The list will expire when modified from the web application. /// (the list can be expired by using Cache.Remove("MeasureList"); /// </summary> public epcdb.MeasureList MeasureList { get { epcdb.MeasureList lst = Cache["MeasureList"] as epcdb.MeasureList; if (lst == null) { lst = new epcdb.MeasureList(); BusinessComponent BC = new BusinessComponent(); BC.Populate(lst); Cache.Add("MeasureList", lst, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.High, null); } return lst; } }
hannes wrote:You may not agree, but I see this method as equivalent to a class implementing the Singleton pattern. (Proper locking is not implemented, but simultaneous access would be harmless.) /// /// A cached list of measurements. /// The list will expire when modified from the web application. /// (the list can be expired by using Cache.Remove("MeasureList"); /// public epcdb.MeasureList MeasureList { get { epcdb.MeasureList lst = Cache["MeasureList"] as epcdb.MeasureList; if (lst == null) { lst = new epcdb.MeasureList(); BusinessComponent BC = new BusinessComponent(); BC.Populate(lst); Cache.Add("MeasureList", lst, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.High, null); } return lst; } }
/// /// A cached list of measurements. /// The list will expire when modified from the web application. /// (the list can be expired by using Cache.Remove("MeasureList"); /// public epcdb.MeasureList MeasureList { get { epcdb.MeasureList lst = Cache["MeasureList"] as epcdb.MeasureList; if (lst == null) { lst = new epcdb.MeasureList(); BusinessComponent BC = new BusinessComponent(); BC.Populate(lst); Cache.Add("MeasureList", lst, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.High, null); } return lst; } }
Shunjie wrote:Example, like keeping a collection of objects which is going to be the same to all user, so like what I did in my previous code, create a single instance of the class, and save it to a Application session.
hannes wrote: /// /// A cached list of measurements. /// The list will expire when modified from the web application. /// (the list can be expired by using Cache.Remove("MeasureList"); /// public epcdb.MeasureList MeasureList { get { epcdb.MeasureList lst = Cache["MeasureList"] as epcdb.MeasureList; if (lst == null) { lst = new epcdb.MeasureList(); BusinessComponent BC = new BusinessComponent(); BC.Populate(lst); Cache.Add("MeasureList", lst, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.High, null); } return lst; } }
Cyrus Crypt wrote:It's amazing how much discussion we can generate from the "simplest" Singleton, huh.I remember someone mentioned that it's too simple to be even worth a thread, but look what depth we are going into. If not for this thread, I would have remained in the impression of a simple Singleton.Let's see what more advanced DP can generate.
Ok Cyrus Cryptie... I admit I was being a Simpleton earlier on the subject but I did some justice to it by starting this thread. So you can stop rubbing it in
Anyway, I'm happy to see so many Paladin code being thrown across the forums nowadays. Really gives me that warm-fuzzy-feelin.
As for all the debates, I still don't know whether which of the methods I posted earlier is correct.
Firedancer wrote:As for all the debates, I still don't know whether which of the methods I posted earlier is correct.