• Post Reply Bookmark Topic Watch Topic
  • New Topic

Please help me to solve the singleton dilema  RSS feed

 
Maulin Vasavada
Ranch Hand
Posts: 1873
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi all,
I have an interface - DataHandler that is implemented as DBDataHandler and LDAPDataHandler classes.
Now, I want to have flexibility where I can switch between any of these two and so I am using Class.forName() where I can pass the class string dynamically. Here is what I do,
DataHandler dh = (DataHandler)Class.forName(runtimehandler).newInstance();
dh.method1();
Finally, my problem is-
I want to make these concrete handlers 'singleton' objects but I can't because if I want to use newInstance() then it has to have a public contructor in it, right? which makes 'singleton' idea fail...
How to overcome this issue?
Please help me to solve my dilema.
Regards
Maulin
 
Mahesh swami
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Using reflection is the only approach to solve your dilemma
Suppose you have a singleton class then you might be having a method to get its instance
say getInstance()
SO you can do
Class cls = Class.forName(runtimehandler);
Method metGetInstance = cls.getMethod("getInstance", null);
DataHandler dh = (DataHandler)metGetInstance .invoke(null, null);
dh.method1();

I hope this solves your problem.
-Mahesh
 
Joel McNary
Bartender
Posts: 1840
Eclipse IDE Java Ruby
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I can actually think of a couple of other ways to implement this. You could create "disposable objects"; that is:
DataHandler dh = ((DataHandler)Class.forName(someName).newInstance()).getInstance();
This would create a "disposable" dh object, whose only purpose is to exist to ensure the correct class's "getInstance()" method is called. Probably not the greatest solution in the world, but it would work.
Probably the better answer (albeit more complex) is to move the onus for returning the correct class to the DataHandler object itself (or, since it's an interface, to a "Factory" class).

And then in each of your subclasses you have a static initializer

Calling "Class.forName(className);" in the getInstance method ensures that the class gets loaded, ensuring that the static initialiazer is run, ensuring that there exists an instance in the instanceMap.
To get the instance, you simply change your method calls from:

to

(Please note that this is how the JDBC DriverManager works; if you ever write a JDBC Driver, you have to include a static intializer to initialize it with the DriverManager)
Hope that this helps.
[ August 28, 2003: Message edited by: Joel McNary ]
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I always think twice when reflection seems necessary. Sometimes it is, but often it is not.
You could make a factory that returns handlers. It could use several strategies: 1) Create a single instance of every possible handler at startup and cache them in a map keyed by type. 2) Use Class.forName().etc() to create a handler the first time somebody asks for one, then cache that instance. This gives a single instance of a handler that is not really a singleton. 3) Reflection, etc.
Options 2 & 3 allow new handler types with zero code changes, even user-installed types that the developer never heard of. Pretty cool.
 
Phil Chuang
Ranch Hand
Posts: 251
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
to abstract things even further, you can then make a DataHandlerResolver class that is basically a map from type to class name, and then pass that to the workfactory to initialize it. The DataHandlerResolver should just be a map that can load its values from a config file (like XML) so that you can update the config file without changing a line of code. I happen to use this xml-resolver-factory-object pattern all the time.
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Maulin, as you can see there are many, many ways to do this (there are in fact much more than discussed here). But without more information, it's impossible to say which one would be right for you.
So, tell us more:
Why do you want to use reflection? Do you really have only this two implementations, or are there possibly more coming? Who will write those implementations?
Why do you want to use something like Singleton?
 
Maulin Vasavada
Ranch Hand
Posts: 1873
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hi Ilja
Sure, I see there are many ways. I would go the way Joel suggested.
Actually I thought of what Joel suggested but I didn't think the way to avoid having public contructor which Joel addresses very smartly. I like it
I was trying to look for "without reflection" solution to avoid unnecessary overhead.
Stan, the way you suggest is correct again but as I want to avoid "named" reference which I would have to make by LDAPHandler, and DBHanlder constructors, it would not be the one applicable here. Also, in my case I would only have one object in the system , either LDAPHandler or DBHandler so I wouldn't want to create both of the objects.
Phil, I am little dumb to get what exactly you mean and I'm looking forward to my NY visit long weekend , so it would be sometime I can research google and try to understand what you suggested before I can comeup with more questions to you
Though, I thank all of you for your suggestions.
Now to address Ilja's questions,
1. Why do you want to use reflection?
- I would want to avoid it if possible as I believe that if there is the other approach (like what Joel points) then reflection might be more work in comparison.
2. Do you really have only this two implementations, or are there possibly more coming? Who will write those implementations?
- I don't think there would be more but DB and LDAP are what I am considering right now. In future it might be XML file storage as well. I am not sure about that.
- I will be the one defining,implementing the interface. Actually, for I'm such a rush that I made the constructors public and made things work for me
3. Why do you want to use something like Singleton?
- The reason I want to use singleton is that my objects that I see as DBDataHandler and LDAPDataHandlers are sort of "manager" objects that communicates with database or ldap in backend to store things. I am planning to use stateless objects (basically passing around Context object for every request, if you know what I mean). One can argue then why not have static methods? Well, I don't know. As I mentioned, I am right now in such a rush of getting things done I can't think I may forget this whole singleton business and declare all static methods with passing Context object to operate upon...
I will give more thoughts to suggestions here and let my mind be at little ease to "think" rather than blindly code and see what do I end up with..
Also, I might create Factory of "Desparate" objects, in comparison of suggested factory of single type of objects by Joel, as these DBDataHandler and LDAPDataHandler are going to be there for each aspect in the application. e.g.
- User/Role/Group management
- Access control
- Application repository storage
you know....
I would be back to senses after long weekends!
Till then,
nJoy!
Regards
Maulin
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Who decides which DataHandler to use? How?
 
Maulin Vasavada
Ranch Hand
Posts: 1873
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Ilja
I read DataHandler from a file called something.properties and there I write,
DataHandler DBDataHandler
or DataHandler LDAPDataHandler
then I read this properties file and load the class that is assigned to DataHandler property..
So, whenever I would change this properties file it will change the implementation handling to DB or LDAP accordingly.
Regards
Maulin
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!