In discussion, I have been introduced to another approach to singletons which might be of interest to some of those having issues with non-deleteable statics. If one defines a class, a singleton manager, if you will, which has a static variable to hold a class instance and a static method to retrieve that instance or simply a static property for the instance, that class can return the instance of a class one desires to be a singleton without the singleton having any statics at all. Thus
class Singletons:
define static property OneX as class X
get():
if OneX = ? then OneX = new X().
return OneX.
end get.
private set.
end class.
then, any code which needs a singleton copy of X can say
MyX = Singletons:OneX.
and get a singleton copy of X. The advantage of this approach is that one can also provide a DeleteX method which gets rid of X, since it has no statics and the only thing that remains in memory is the Singletons class. And, the Singletons class could manage multiple singleton classes, although, of course, there is an issue of coherency there. And, if one wanted, one could supplement the get with reference counting, provide a method for decrementing the count, and provide one's own garbage collection on the singletons.
Naming is, as usual, up to personal taste.
Not beautiful, but it might get someone past some of the sticky issues of using statics.
err, this is old hat ... We use this mechanism all the time now, for the reasons you mention (unloading if required etc)
2009 http://communities.progress.com/pcom/message/27913#27913
2010 http://communities.progress.com/pcom/message/85780#85780
It is old hat to have a class with a singleton getInstance method or Instance property which returns an instance of *that* class. But, that means that one has a class which has at least that one static element. In this case, the class returned is *not* the class in which the static resides, so there are *no* static elements in the singleton class.
from dotr.hash42 (16 months old .. )
using Progress.Lang.*.
using dotr.hash42.Config.Asterisk.*.
/** instance handler
* this class manages all the instances for the various singleton library classes */
class dotr.hash42:
/** the skin instance for hash42 */
def public static property Skin as class dotr.hash42.UI.Library.Skin no-undo
get():
if not valid-object(Skin) then Skin = new dotr.hash42.UI.Library.Skin().
return Skin.
end get. private set .
/** windows API instance */
def public static property WindowsAPI as class dotr.hash42.Utils.WindowsAPI
get():
if not valid-object(WindowsAPI) then WindowsAPI = new DotR.hash42.Utils.WindowsAPI().
return WindowsAPI.
end get. private set .
/** the Session instance for hash42 */
def public static property Session as class dotr.hash42.Session
get():
if not valid-object(Session) then Session = new dotr.hash42.Session().
return Session.
end get. private set .
end class.
tamhas wrote:
It is old hat to have a class with a singleton getInstance method or Instance property which returns an instance of *that* class. But, that means that one has a class which has at least that one static element. In this case, the class returned is *not* the class in which the static resides, so there are *no* static elements in the singleton class.
guess that 'old hat' is what a singleton is all about... if the class really is a singleton then the fact that there should be only one instance of it should be enforced by the class itself and don't rely on somebody else to do it.
that new version of singleton looks more like a service factory to me, something that could also serve very well for things like dependency injection but I wouldn't call that 'singleton'
Thank you for your message. I am currently out of the office, with limited access to email.
I will be returning on Monday, 03/19/12.
Brent
that new version of singleton looks more like a service factory to me, something that could also serve very well for things like dependency injection but I wouldn't call that 'singleton'
Unless the class instance itself verifies using the service factory that it is the one and only instance of that class.
But that will create a dependency between the class and the service factory that may not be desired at all.
marianedu wrote:
guess that 'old hat' is what a singleton is all about... if the class really is a singleton then the fact that there should be only one instance of it should be enforced by the class itself and don't rely on somebody else to do it.
that new version of singleton looks more like a service factory to me, something that could also serve very well for things like dependency injection but I wouldn't call that 'singleton'
you can ensure that the singleton cannot get created by anything else but the "session library" by making the constructor of the singleton take a session library key as a parameter, and making the default constructor private.
fugly, but it works
The real important thing about the "new singleton" is that as it has *no* static members, so the entire class is not permanently loaded into memory, with all the associated problems that has.
jmls wrote:
marianedu wrote:
guess that 'old hat' is what a singleton is all about... if the class really is a singleton then the fact that there should be only one instance of it should be enforced by the class itself and don't rely on somebody else to do it.
that new version of singleton looks more like a service factory to me, something that could also serve very well for things like dependency injection but I wouldn't call that 'singleton'you can ensure that the singleton cannot get created by anything else but the "session library" by making the constructor of the singleton take a session library key as a parameter, and making the default constructor private.
fugly, but it works
The real important thing about the "new singleton" is that as it has *no* static members, so the entire class is not permanently loaded into memory, with all the associated problems that has.
sure you can, hopefully there is something like an IService interface that need to be implemented by those 'services' - might also have a method called isSingleton to let the service factory new what to do when a new service instance is requested... the point is, this is not a singleton as we know it so I don't see why we have to name different things the same way, doesn't look very helpful for me
and this also implies that your 'session factory' is a singleton itself otherwise different instances of it would each instantiate one service 'singleton'.
mikefe wrote:
Unless the class instance itself verifies using the service factory that it is the one and only instance of that class.
But that will create a dependency between the class and the service factory that may not be desired at all.
even if the dependency is something desirable or accepted the singleton would have to rely on the factory to be a singleton, otherwise different factory instances will load separate instances of our singleton... having a public constructor that gets the factory as input still leave it open for others to get around the factory and call it directly, if there is already an instance there is no way to return that particular instance from the constructor and the only option would be to throw an error... this doesn't look like what a singleton should do does it?
by definition, the "session factory" (see, even this old brain is still capable of picking up the new jargon for doing old things) is a pure singleton, with nothing but static properties . There is no logic in there except that to get the instance of the other "Single Instance Classes".
Perhaps we should define these classes as SIC
it's back to the old proposition - if a developer has access to source
code, they can always find ways to subvert the system. In a true
singleton, they could change the private constructor to be public and
create a new instance that way.
My guys don't want to subvert the system - they just want an easy way
to ensure the right things are running without having to remember to
instantiate everything.
jmls wrote:
it's back to the old proposition - if a developer has access to source
code, they can always find ways to subvert the system.
you don't have to have access to the source code to call a public constructor that just sits there, a singleton doesn't have a public constructor... it's advisable to make it protected though (for unit testing, see Tim's post on your other thread about statics... find that the hard way myself ).
but after all if you like to call that the new singleton I don't have any issue with it
to be perfectly honest, I am finding that I am falling out of favour with singletons or statics of any sort, with the possible exception of a single entirely static class consisting of just static properties for things like TerminalID, SessionGUID etc
unless you have a really tight loop spanning several thousand iterations, instantiating a new instance (especially with -q ) is so relatively fast the startup time is not noticable.
in fact, the latest iteration of Maia does away with the static helper classes entirely
we used to say
message dotr.Maia.Sports:Helper.Customer:Find(123):Cust-name view-as alert-box
we now say
message (new Model.Customer()):Find(123):Cust-name view-as alert-box
or
message (new Model.Customer(123)):Cust-name view-as alert-box
in other scenarios where we used to say
dotr.Hash42:PBX:ConferenceRoomList()
we now say
(new dotr.Hash42.PBX():)ConferenceRoomList()
both the above mechanisms take less than a millisecond to load and execute, so to my mind there is no point in having the static dotr.Hash42 class
This was a big thing with 10.1 (possibly 10.2A (can't remember)) , as there was no abl garbage collection, so doing the (new foo()) actually physically caused a memory leak. In this case we had to do the following
def var a as dotr.Hash42.PBX.
a = new dotr.Has42.PBX().
a:ConferenceRoomList().
delete object a.
because of this, it made sense to have a static helper or property pointing to an instance of dotr.Hash42.PBX
Since we now have the automatic GC , the disposal of the temporary instance is now handled for us, and we can do (new dotr.Hash42.PBX():)ConferenceRoomList() with impunity
IMHO there is no need now to have singletons / statics with the exception of the edge case described in the first sentence.
Having bashed this thoroughly in the ground, a couple of points:
* "New" is not the right word. "Another" is a better word. Not that people haven't done it before, but that I haven't seen it documented here before. In fact, the source was not new at all, but rather the other way around.
* Yes, as a general rule, one would prefer that the class enforce its own singletonness. Obviously. I offered this simply for those cases where there was a reason why people were reluctant to use statics to create a singleton. If one does not have those concerns, it is clearly better for the class to do it itself because it is more cohesive, more positive, and avoids the use of a helper class.
* Which said, I agree that singleton's and statics are often over used. Often, the singleton nature of a class is something inherent in its relationships and there is actually no need to enforce that with special coding. Statics are often used as a fancy version of a global variable and are equally dubious. They have some very valuable uses, but one should try to talk oneself out of them before blithly using them.
If you want to see some interesting uses for singletons, check out how some languages like Ruby or Smalltalk implement metaclasses. Ruby's metaprogramming abilities that arise from this, in particular, make it quite powerful.
jmls wrote:
to be perfectly honest, I am finding that I am falling out of favour with singletons or statics of any sort, with the possible exception of a single entirely static class consisting of just static properties for things like TerminalID, SessionGUID etc
IMHO there is no need now to have singletons / statics with the exception of the edge case described in the first sentence.
I generally agree with limiting the use of singletons and static members - but wanted to point out that these 2 are not interchangable terms. You can create singleton classes that don't use statics.
-- peter
tamhas wrote:
* Yes, as a general rule, one would prefer that the class enforce its own singletonness. Obviously. I offered this simply for those cases where there was a reason why people were reluctant to use statics to create a singleton. If one does not have those concerns, it is clearly better for the class to do it itself because it is more cohesive, more positive, and avoids the use of a helper class.
I don't believe types should manage their own lifecycles at all. They do what they're supposed to do, according to the SRP. Someone else's R is to manage their lifecycles.
-- peter
I don't see an object managing its singletonness as the same as it managing its own lifecycle. Yes, for most objects, someone else decides when it is needed and when it is no longer needed. But the idea that there is only ever supposed to be one of something is a property of the thing. It is just that using statics to implement that can have unpleasant sideeffects in some cases.
Of course, I think there is also a temptation for some people to force something to be a singleton when there is no particular need to do so. Often, the singletonness is inherent in the object's relationships and there is no need to force.
Yes, one can, but it requires a kludge like this technique or the facade/implementation approach I defined on OE Hive to completely avoid statics.