conditional object creation

Started by
10 comments, last by dmatter 10 years, 8 months ago

Hi there,

i'm currently trying to write a kind of XML-Parser for my gui framework and i'm struggling with the object creation.

So a possible XML-File could look like this:


<Window id="Notification" title="Notification" message="An Error occured while...">
   <button id="Button_try_again" caption="Try again" />
   <button id="Button_cancel" caption="cancel" />
</Window> 

For iterate through all tags i'm using StaX. The name of each tag is accessible by calling the getLocalName()-method.

Furthermore there is an corresponding class for each valid tag (just like window and button in the example above) and i need to get an object of one of them.

So here is a little snippet of what came to my mind to achieve this:


String tagname = Staxparser.getLocalName();

if(tagname.equalsIgnoreCase("Window")) {
     // instantiate window class
} else if(tagname.equalsIgnoreCase("Button")) {
     // instantiate button class
}

Well, this looks pretty much nasty and should not be done like this.

So here is the actual question:

Is there a way to not use a whole bunch of if-else-statements to figure out what class needs to be instantiated?

Is there a design pattern or anything else that is able to simplify the problem?

Thanks in advance.

Advertisement

A common solution for this type of problem is to use a dictionary structure as a "catalog" or a "type repository". The keys for such a dictionary would be the type names that can be instantiated, and the values would be simple structures that could contain, among other things, a pointer to the constructor of the given type.

At your convenience (for example, app startup), you would add the instantiable types to your catalog dictionary; later, when you enumerate through the xml, you would simply look up each element from the catalog and instantiate them using the info in the catalog values.

The catalogs could be constructed by inspecting actual classes and/or modules using reflection at runtime, as opposed to hardcoding the object data to the catalog in your code. This way, your application core doesn't have to care about which actual classes are created in the end (but be sure to provide common interfaces to all the objects so that you can actually use them in the core application somehow).

Even though you use Java, it may be worthwhile to check out Microsoft's MEF architecture for inspiration. It is not as difficult to implement by yourself as one would think.

Niko Suni

.Net and Java basically already grant you the abilities to do this in their frame works and the thing you are looking for is called reflection. Effectively this allows you to create objects that are defined in your program by only knowing their names, without having to write any special code to track what can be created as described by Nik02..

Reflection in both languages are advanced features and you might need to experiment a little bit with what you have to specify in the names.

In C++ you can actually construct this list at compile time through some macro tricks and function pointers, it is not a nice solution to look at but this achieves what nik02 describes:

http://code.google.com/p/dxengine/source/browse/trunk/src/ClassRegistration.h

http://code.google.com/p/dxengine/source/browse/trunk/src/Misc/ObjectFactory.h

and these two macros:


//This goes in the header of the class
#define REGISTER_CLASS(CLASS) static const ClassRegistrar s_registration##CLASS;
//this goes in the cpp of that class
#define DL_REGISTER(CLASS) const ClassRegistrar CLASS::s_registration##CLASS(&CLASS::m_rttiInfo, #CLASS,&ObjectFactory::objectCreationFunctionTemplate<CLASS>); 

The only reason I ever wrote this code was because I wanted to know how this could work in C++, there are other ways of achieving this in nicer ways probably.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

[ edit ]...what NightCreature83 said.

This doesn't change things in a absolute sense. Someplace, under-the-hood or not, there will be a loop, if-else-if cascade or switch statement that ends up instantiating types from strings. The only difference is where this code exists and who wrote it (you, the compiler, an API or a synergistic combination).


This doesn't change things in a absolute sense. Someplace, under-the-hood or not, there will be a loop, if-else-if cascade or switch statement that ends up instantiating types from strings. The only difference is where this code exists and who wrote it (you, the compiler, an API or a synergistic combination).

At some point or another, there has got to be some controll structure to make things work. Such structures are the first main feature that differ programming languages from descriptive languages like HTMl, etc... . You can't just expect to get rid of all if-else by some kind of black magic, and why would you want to in the first place? What the OP wants makes sense, he wants to get rid of a potential hundreds of nestes if-else's to read all possible types of gui elements in, therefore also making things more modular.

To be all honsest, I personally would just create a ILoadRoutine-interface, and derive for each widget(type?) an implementation from it. Then store those by string in an array or such structure, look them up by the name of the tag, and call a "Create(...)"-method. In this method, you handle the instantiation of the class, and all proper setup. Thats how I'd do it, would even work without any if/else, but don't know if this is a commonly seen good method or not...

If the only difference between instantiate window class and instantiate button class is the class name, then reflection is the way to go. Something like:
Class.forName(tagname).newInstance()

Be sure to sanitize and verify the correctness of the input.
Marshalling XML to and from Java objects is a solved (and not very interesting) problem, Java actually has built in support for XML-binding called JAXB which will just take care of it all for you. There are similar other 3rd party libraries that essentially do the same thing too.

Hi there,

i'm sorry for not replying until now.

So there are 3 Options i can choose from:

  • a catalog system to map the elements used in the xml to its corresponding entities
  • reflection
  • existing xml marshalling frameworks like JAXB

So i tried out the reflection approach during the weekend and at some point i realized that i am not able to generalize all possible entities due to the fact that a button maybe has different attributes than a label.

A catalog system seems to be a much easier way to handle this. But in my opinion there is another problem:

For every entry in the catalog system, representing a special widget, there must be another dictionary that contains every possible attribut for that special widget. This can grow a lot since more and more widgets are implemented.

In the end i will try out JAXB. As far as i read through some examples its mostly based on annotations and should be working fine.

So thanks to all of you for your advices, it helped me a lot.

In the end i will try out JAXB. As far as i read through some examples its mostly based on annotations and should be working fine.
So thanks to all of you for your advices, it helped me a lot.

It's been a while but my memory of it is that most (all?) of the annotations are actually optional and, if not used, JAXB will employ "convention over configuration" and just directly use the names of methods/classes/etc as long as you stick to standard java-bean naming conventions (i,.e. setCaption and getCaption etc).

For every entry in the catalog system, representing a special widget, there must be another dictionary that contains every possible attribut for that special widget.

You are making a xml file with many different objects alive in your system side. The fact that you instantiate proper objects on those types, will not somehow miracly get you rid off managing them and aproaching them the way their datatype demands (a label is not window so much). You should rethink deeply not only instantiating them conditianaly, but runinng them conditionaly. The aproach I use is that I use inharitance and that I have an all shared class, and inside that most basic class I have an int that detects their highest datatype- the type. This gives me assurance that anywhere in my code ever I will be able to do type conditional aproaches to them. The nummber in the most basic class is simply set in constructor of any class that inherits the all shared class.

This topic is closed to new replies.

Advertisement