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\$
  • \$\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\$ – J_F_B_M Aug 20 '14 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\$ – J_F_B_M Aug 20 '14 at 14:15
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\$
  • \$\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 '14 at 14:57
  • \$\begingroup\$ @Salor in this case refer to second part of the answer. I made a bit clearer were it starts ;) \$\endgroup\$ – J_F_B_M Aug 20 '14 at 15:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.