views:

423

answers:

4

Let's suppose I have an interface named "Controller". Several classes implement this interface and I don't know these classes (e.g. the class names are located in an xml-file). Now for this Controller-implementing classes to work they have to get some references to other objects (maybe data objects). And this is my question, namely what is the best way to initialize such objects (the Controller ones)?

I thought of several solutions but I'm not really sure what's the best approach here.

First: When instantiating the object from the class name I could search for the "special" constructor (via reflection) which has the object references that the Controller-object needs. But from what I read in other questions this is less likely a good solution because I would force a special constructor to exist in the class. And sometimes I read that reflection in general is evil and is better avoided.

Second: I add a special init(a,b,c)-method to the Controller-interface which would need to be called directly after the object was created. This would force a sequence of calls (first init(..), then rest) to the object to make it working which is likely bad too. Btw, are init()-methods generelly a bad thing in interfaces?

Third: After reading this comment I thought about the following: Instead of having the class name of the class implementing the Controller-interface (in the xml file) I have the class name of a factory which belongs to the concrete Controller-class. And this factory would implement an interface with the method createController(a,b,c) and the factory then would know which class it would have to instantiate and also which constructor to call to carry over the other references (like data objects). Drawback of this would be the additional class just to instantiate the Controller-class and maybe a little overhead in general.

What do you think is the best way of doing this? Or can you think of something else which might be better than these three ways?

Thanks!

+4  A: 

Of the approaches you mention, I'd pick the second (factory-based one). However, since what you're doing is a form of dependency injection, also consider Guice, http://code.google.com/p/google-guice/ -- it may enable you to automate much of this work.

Alex Martelli
+1 one for Guice-type things. Second option is two phase construction. Did you meant the third option?
Tom Hawtin - tackline
Thanks! I already looked a bit into Guice some time ago but I haven't really realised until now that it is what I'm already doing - just manually. The problem is that this is for an already grown university project. I would love to use it but I think this would not be easily possible atm. I think I will stick to the factory solution.
neo
Just a little note - I use Guice in a new project and I love it. So thanks for recommendation!
neo
@neo, you're welcome -- I'm no Java expert, but it does seem to me that my colleagues who developed Guice did a good job!-)
Alex Martelli
A: 

In something similar in another language, I've been known to use the init() solution.

Joshua
+2  A: 

What you are trying to do is very similar to what Spring does. In your xml file, your controller node would have child nodes to specify properties to be set. Your controller is instatiated by calling the default constructor. Then properties are set using reflection.

svachon
+1 for Spring. Some examples of Spring configurations: http://static.springframework.org/spring/docs/2.0.x/reference/beans.html#beans-some-examples
Adam Paynter
+1 For Spring. It seems you are trying to write a dependency injection of your own. There are many (Spring, Guice, Seam, just to name a few) so this is quite redundant.
David Rabinowitz
Looks also quite interesting, I will definitely use such a framework the next time, but for now it would be too much work to integrate one of these like I explained in the comment regarding Guice.
neo
A: 

Another option could be to use the Unsafe.allocateInstance(Class) to create an instances without calling a constructor. You can set the fields using reflections.

This assumes that your constructors don't have any side effects.

Peter Lawrey
Hm seems a bit hacky, with that I would need to force certain field names or put these in the xml too.
neo