This week's book giveaway is in the Other Languages forum.
We're giving away four copies of Rust Web Development and have Bastian Gruber on-line!
See this thread for details.
Win a copy of Rust Web Development this week in the Other Languages forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • Ron McLeod
  • Liutauras Vilda
  • Jeanne Boyarsky
Sheriffs:
  • Junilu Lacar
  • Rob Spoor
  • Paul Clapham
Saloon Keepers:
  • Tim Holloway
  • Tim Moores
  • Jesse Silverman
  • Stephan van Hulst
  • Carey Brown
Bartenders:
  • Al Hobbs
  • Piet Souris
  • Frits Walraven

Please help me to solve the singleton dilema

 
Ranch Hand
Posts: 1873
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • 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
 
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • 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
 
Bartender
Posts: 1843
Eclipse IDE Ruby Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • 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 ]
 
(instanceof Sidekick)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • 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.
 
Ranch Hand
Posts: 251
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • 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.
 
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • 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
    Number of slices to send:
    Optional 'thank-you' note:
  • 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
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Who decides which DataHandler to use? How?
 
Maulin Vasavada
Ranch Hand
Posts: 1873
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • 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
reply
    Bookmark Topic Watch Topic
  • New Topic