views:

87

answers:

4

Let's say I have a lot of similar classes (Units in a RTS in this example), that is, the class Unit, and the subclasses UnitA,UnitB,UnitC etc.

All Unit classes have the following constructor (including Unit)

public class UnitX {
    public UnitX(FileReader fr) {
         ...read parameters for constructing the unit...
    }
}

My file containing the parameters have the form

UnitX params
UnitY params
....

and creating a list of all units in a file would be a while-loop like

Class[] params = {FileReader.class};
while(fr has more to read) {
    String unitType = fr.getString();
    Unit u = (Unit)
java.lang.reflect.Constructor constr = Class.forName(unitType).getConstructor(params);
    Unit u = (Unit)constr.newInstance(new Object[]{fr});
    list.add(u);
}

I realized that I use this pattern very often when I create objects from files. My question is, is this a bad pattern? Is there a better way to do this?

A: 

This is a simple, cut down serialization. I would say that this is fine if it fits your purposes.

krock
A: 

I think your implementation is ok. Another approach: the textfile is a simple form of a DSL (Domain Specific Language)

You could switch to a more dynamic jvm compatible language. Dynamic languages like groovy (my favourite ;-) ), javascript (Rhino,...), BeanShell, jython, ... can more easily be used to implement Domain specific languages (DSL). For more complex DSL's, you could take a look at the eclipse XText project.

tweber
+2  A: 

The code itself is fine. Since constructors cannot be part of a traditional codified interface, the next best thing is the consistent reflective interface.

However, if you are repeating this code in many places, then that's not so good. You might try to centralize that into some kind of factory or builder that provides Unit names from the file, along with the parameters defined for that unit, and pair this with a handler implementation that instantiates the unit with the parameters provided via a UnitFactory. The UnitFactory uses reflection to instantiate the named Unit and provide it with the parameters.

This allows reuse, and decouples reading the file from instantiation, and the method of instantiation.

mdma
Isn't it more reasonable that the unit classes themselves providesthe method for reading/writing their states to a filer reader/writer?An additional unit class would not require a change in my factory class.
Paxinum
Yes, that's also possible, just be aware you are then mixing responsibiliites, but so long as you are aware of that and what it might mean then it's ok. Unit tests are usually intentionally simple, so a more direct, coupled approach is often the best fit, since it's clearer.
mdma
+2  A: 

That a case for the factory pattern:

java.lang.reflect.Constructor constr = Class.forName(unitType).getConstructor(params);
Unit u = (Unit)constr.newInstance(new Object[]{fr});

could be changed into

Unit u = UnitFactory.create( unitType, fr );

The factory is then a list of if/else though.

ewernli