3
\$\begingroup\$

I want to use a HashMap to dynamically create objects based on the key.

I have a Random Map Generator that stores the maps in 3D Arrays of Type Integer[][][]. Upon creation of the actual map I iterate through this array and based on the Integer I want to create the right block.

Example: Integer[][][] map ... map[6][6][6] = 3; 3 is a Earth-Block and now I want to initialize a new Block of this type and give it the right coordinates.

Currently I store my Bindings from Integer to Class in a HashMap(Integer, String) and create my objects like that:

int id = array[x][y][z];
String block_name = Blocks.map.get(id);

Block block = (Block) Class.forName(block_name).newInstance();
block.setPosition(x,y,z);

But I want to avoid newInstance() if possible.

I've never worked that dynamically with Java before and I couldn't find a solution like changing the HashMap to (Integer, Class) or something. I just need to create a new Object based upon the Integer.

Any ideas/solutions? Thanks in advance and have a wonderful day!

\$\endgroup\$
2
  • \$\begingroup\$ Maybe a map that matches together IDs and BlockFactorys, which have a static newInstance()-method. So you do block = blockFactorys.get(id).newInstance(). This would however generate lots of new classes. A BlockClass could even be its own factory. This would kill the additional classes. \$\endgroup\$
    – JFBM
    Aug 20, 2014 at 14:10
  • \$\begingroup\$ Btw, it comes to my mind that this would better be placed on codereview-SE, because you have working code which simply needs to be refined. \$\endgroup\$
    – JFBM
    Aug 20, 2014 at 14:15

1 Answer 1

1
\$\begingroup\$

Invalidated by asker

If you don't mind to use the same Block over and over again, simply do a mapping Integer→Block.


Answer starts here

Otherwise, you could use some kind of factory-pattern.

You store a mapping Integer→BlockFactory, where BlockFactory is an instance of the Factpry corresponding Block. You then have a newInstance(/*params*/) method which would create a Block on runtime.

public DirtFactory extends BlockFactory
{
    @Override
    public Block newInstance(int x, int y /*...*/)
    {
        Dirt d = new Dirt();
        d.x = x; d.y = y; /*...*/
        /* do other stuff if necessary*/
        return d;
}  

.

/*only the code from id to block */
HashMap<Integer,BlockFactory> mapping = new HashMap<>();

/*fill your HashMap with Instances of your BlockFactorys at the start of your game*/

int id = array [13][3][7];
Block b = mapping.get(id).newInstance(/*params*/);

Now you have your Block saved in b.
You will not come around a newInstance () in some way (a copy() is also some kind of newInstance() ). But I consider my solution better than using the Class-class.
If you want to save class-Definitions, you can embed the functionality of the Factory in the corresponding Block, however this gets messy very, very fast and is not recommended.

Note to programmers: I know this is not the nicest representation for the Factory-Pattern, but should do the trick here quite well.

\$\endgroup\$
2
  • \$\begingroup\$ I do mind using the same block over and over again, because if it was destroyed there would be quite a mess ;) Every block needs to be another object. \$\endgroup\$
    – Salor
    Aug 20, 2014 at 14:57
  • \$\begingroup\$ @Salor in this case refer to second part of the answer. I made a bit clearer were it starts ;) \$\endgroup\$
    – JFBM
    Aug 20, 2014 at 15:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .