design pattern question

J

Josef Garvi

I have a file that may contain different types of data.
Depending on the contents of the file, I would like to create different
types of objects. Is there a way that I can let my file parsing class know
what processing classes are available, so that it can create an instance of
the appropriate class?

I would prefer not having to couple my file parser class to the processing
classes, so that I could add new processing classes for other data types
without having to modify the code of the file parser in any way. How can I
solve this? Is there for example a way of finding all classes in a package,
so I can load them and have them register themselves with the file parser
in their static initialisers?
Or am I forced to hard-code the names of all processing classes in my file
parser class?

--
Josef Garvi

"Reversing desertification through drought tolerant trees"
http://www.eden-foundation.org/

new income - better environment - more food - less poverty
 
T

Thomas Weidenfeller

Josef said:
I have a file that may contain different types of data.
Depending on the contents of the file, I would like to create different
types of objects. Is there a way that I can let my file parsing class
know what processing classes are available, so that it can create an
instance of the appropriate class?

Your description is vague, so here are some vague suggestions:

Consider using some kind of factory/kit class or method. Consider using
reflection to create instances from parsed type names (strings).

Alternatively, or in addition, consider using a prototype repository,
where all handlers register a prototype of a handler object (or just a
corresponding class object). The repository might use a hashmap to map
parsed type names (strings) to object prototypes (or class objects).
When a particular object is needed, clone the prototype object (or use
the class object to create an instance).
Is there for example a way of finding all
classes in a package,

This is an FAQ and has been answered here a thousand time. And the
answer is:

No, not in a general way.

If you add restrictions (e.g. all handler .class files must reside in
one particular directory), you can find them with the normal File methods.
Or am I forced to hard-code the names of all processing classes in my
file parser class?

No. You could e.g. use a configuration file, e.g. a properties file,
listing all handler classes and their location.

/Thomas
 
J

Josef Garvi

Thomas said:
Alternatively, or in addition, consider using a prototype repository,
where all handlers register a prototype of a handler object (or just a
corresponding class object). The repository might use a hashmap to map
parsed type names (strings) to object prototypes (or class objects).
When a particular object is needed, clone the prototype object (or use
the class object to create an instance).

That's my line of thinking. A HashMap would work well for creating objects
based on data type. The question is just how I register my classes in the
HashMap. The nicest thing would be if they could plug themselves into the
HashMap by themselves. I.e. if I add a new class with appropriate methods,
it would register itself into the map. I have tried putting that code into
a static initialiser, but the static initialiser only gets called when some
code in the program refers to the class, making the class-loader load it.
Assuming I have not referenced the classes when I read the file, I will
have an empty HashMap...
(this would have been different in language like Delphi, where all linked
units are initialised when the program loads rather than "on-demand")

Your two suggestions about checking for all .class files in a particular
directory, and creating a configuration file holding the names of all
classes are both possible solutions.


--
Josef Garvi

"Reversing desertification through drought tolerant trees"
http://www.eden-foundation.org/

new income - better environment - more food - less poverty
 
R

Roedy Green

Is there a way that I can let my file parsing class know
what processing classes are available, so that it can create an instance of
the appropriate class?

I think you are hinting that you want class.forName. See
http://mindprod.com/jgloss/classforname.html

You write various parser classes that implement an Interface. You can
dynamically load new parsers simply by providing a text file at run
time with the names of the parsing classes. To see how the technique
works see http://mindprod.com/holidays.html

Each different holiday calculator is a class that implements the
HolInfo interface. There is a properties file that lists which
HolInfo-implementing classes you want to work with. You can then add
new classes without recompilation.
 
R

Roedy Green

I have tried putting that code into
a static initialiser, but the static initialiser only gets called when some
code in the program refers to the class, making the class-loader load it.
Assuming I have not referenced the classes when I read the file, I will
have an empty HashMap...

There is no problem having a class register itself.

Typically you have a text file with a list of classes to register.

Alternatively you could write a sniffer that looked at every class on
the classpath and decided if it fit the pattern of an autoloading
class. Then all you need do add new parsers is name them
appropriately and put them on the classpath. You might put them all in
a jar to make them easier to find.

If the class matches the pattern (e.g. implements your interface), you
load it, and it registers itself with a static initialiser. See
http://mindprod.com/jgloss/jasm.html
for how you could tell what interfaces a class implemented before you
loaded it.

With the text file approach, you don't necessarily load the class
until you need it.
 
J

Josef Garvi

Roedy said:
There is no problem having a class register itself.

Typically you have a text file with a list of classes to register.

Yes, that's possible. The drawback here is that it doesn't work well with
refactoring.

Alternatively you could write a sniffer that looked at every class on
the classpath and decided if it fit the pattern of an autoloading
class. Then all you need do add new parsers is name them
appropriately and put them on the classpath. You might put them all in
a jar to make them easier to find.

That's an interesting approach. Do you have any "getting-started" advice on
how to write a sniffer? (i.e. which classes should I use). Or is it all
done with Jasm?


--
Josef Garvi

"Reversing desertification through drought tolerant trees"
http://www.eden-foundation.org/

new income - better environment - more food - less poverty
 
R

Roedy Green

That's an interesting approach. Do you have any "getting-started" advice on
how to write a sniffer? (i.e. which classes should I use). Or is it all
done with Jasm?

Bone up on ClassLoaders.

You have the System Properties which tell you the path and classpath.
You can parse that yourself.

If you know the name of the jar file, you can use the Zip classes to
go looking around inside it for a list of class names. In a primitive
scheme, the class names you are looking for just fit some
regex/wildcard pattern.

In a sexier scheme all the autoloading classes have to do is implement
some Interface. To discover which interfaces a class implements
without loading it, you must read the class as a string of bytes and
analyse it. Tools for doing that are discussed at
"http://mindprod.com/jgloss/jasm.html"
Tho tools themselves are typically written in ordinary Java. To them
the class files are just a complicated string of bytes.

If you LIKE the class file, then you load it with class.forName.

See http://mindprod.com/jgloss/classforname.html
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top